From 32d00e7c97105cb380d0d1343f1b023061803be6 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 3 Apr 2023 13:03:54 +0200 Subject: [PATCH 001/163] Add foundry config --- .gitignore | 4 ++++ foundry.toml | 14 ++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 foundry.toml diff --git a/.gitignore b/.gitignore index 73fcc1925c..b8c56165fa 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,7 @@ cache build artifacts deployment.json + +#Foundry files +out/ +forge-cache/ \ No newline at end of file diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 0000000000..922e8d94a2 --- /dev/null +++ b/foundry.toml @@ -0,0 +1,14 @@ +[profile.default] +src = 'contracts' +out = 'out' +libs = ["node_modules", "lib"] +test = 'test/foundry' +cache_path = 'forge-cache' +optimizer = true +optimizer_runs = 20000 +via_ir = false + +[fmt] +number_underscore = 'thousands' +line_length = 100 +# See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file From 694f54ae02ac92bc6a2d4ce48449b5c90aa188c9 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 3 Apr 2023 13:05:17 +0200 Subject: [PATCH 002/163] forge install: forge-std v1.5.2 --- .gitmodules | 3 +++ lib/forge-std | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 lib/forge-std diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..888d42dcd9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 0000000000..2b58ecbcf3 --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 2b58ecbcf3dfde7a75959dc7b4eb3d0670278de6 From 80b57136c3c139a7d40be11a81c5ed3ad5e886d8 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 4 Apr 2023 16:05:56 +0200 Subject: [PATCH 003/163] Add 1st Foundry testcase --- .gitmodules | 2 +- remappings.txt | 7 +++ test/foundry/L1ERC20Gateway.t.sol | 90 +++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 remappings.txt create mode 100644 test/foundry/L1ERC20Gateway.t.sol diff --git a/.gitmodules b/.gitmodules index 888d42dcd9..4c1b977a36 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "lib/forge-std"] path = lib/forge-std - url = https://github.com/foundry-rs/forge-std + url = https://github.com/foundry-rs/forge-std \ No newline at end of file diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 0000000000..18d5a0c9ed --- /dev/null +++ b/remappings.txt @@ -0,0 +1,7 @@ +ds-test/=lib/forge-std/lib/ds-test/src/ +forge-std/=lib/forge-std/src/ +@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/ +@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ + + + diff --git a/test/foundry/L1ERC20Gateway.t.sol b/test/foundry/L1ERC20Gateway.t.sol new file mode 100644 index 0000000000..bb1d7d8e30 --- /dev/null +++ b/test/foundry/L1ERC20Gateway.t.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity 0.6.11; +pragma experimental ABIEncoderV2; + +import "forge-std/Test.sol"; +import "contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol"; +import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; +import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract L1ERC20GatewayTest is Test { + L1ERC20Gateway public l1Gateway; + IERC20 public token; + + // gateway params + address public l2Gateway = address(1000); + address public router = address(1001); + address public inbox = address(new InboxMock()); + address public l2BeaconProxyFactory = address(1003); + bytes32 public cloneableProxyHash = + 0x0000000000000000000000000000000000000000000000000000000000000001; + + address public user = address(1004); + + function setUp() public { + l1Gateway = new L1ERC20Gateway(); + l1Gateway.initialize(l2Gateway, router, inbox, cloneableProxyHash, l2BeaconProxyFactory); + + token = IERC20(address(new TestERC20())); + + // fund user and router + vm.prank(user); + TestERC20(address(token)).mint(); + vm.deal(router, 100 ether); + } + + /* solhint-disable func-name-mixedcase */ + function test_initialize() public { + assertEq(l1Gateway.counterpartGateway(), l2Gateway, "Invalid counterpartGateway"); + assertEq(l1Gateway.router(), router, "Invalid router"); + assertEq(l1Gateway.inbox(), inbox, "Invalid inbox"); + assertEq( + l1Gateway.l2BeaconProxyFactory(), + l2BeaconProxyFactory, + "Invalid l2BeaconProxyFactory" + ); + assertEq(l1Gateway.whitelist(), address(0), "Invalid whitelist"); + } + + function test_outboundTransfer() public { + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + // retryable params + uint256 maxSubmissionCost = 1; + uint256 maxGas = 1000000000; + uint256 gasPrice = 3; + uint256 depositAmount = 300; + bytes memory callHookData = ""; + bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); + + // approve token + vm.prank(user); + token.approve(address(l1Gateway), depositAmount); + + vm.prank(router); + l1Gateway.outboundTransfer{ value: maxSubmissionCost + maxGas * gasPrice }( + address(token), + user, + depositAmount, + maxGas, + gasPrice, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + } +} From 20d53a944951c49ce84160714dc56c9c06f316e7 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Apr 2023 11:41:28 +0200 Subject: [PATCH 004/163] Add eth/erc20 inbox mock --- contracts/tokenbridge/test/InboxMock.sol | 54 ++++++++++++++++++------ 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/contracts/tokenbridge/test/InboxMock.sol b/contracts/tokenbridge/test/InboxMock.sol index 33a557ddb4..abb400e90d 100644 --- a/contracts/tokenbridge/test/InboxMock.sol +++ b/contracts/tokenbridge/test/InboxMock.sol @@ -22,13 +22,31 @@ import "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import "@arbitrum/nitro-contracts/src/bridge/IBridge.sol"; import "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; -contract InboxMock { +abstract contract AbsInboxMock { address l2ToL1SenderMock = address(0); event TicketData(uint256 maxSubmissionCost); event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); event InboxRetryableTicket(address from, address to, uint256 value, uint256 maxGas, bytes data); + function bridge() external view returns (IBridge) { + return IBridge(address(this)); + } + + function activeOutbox() external view returns (address) { + return address(this); + } + + function setL2ToL1Sender(address sender) external { + l2ToL1SenderMock = sender; + } + + function l2ToL1Sender() external view returns (address) { + return l2ToL1SenderMock; + } +} + +contract InboxMock is AbsInboxMock { function createRetryableTicket( address to, uint256 l2CallValue, @@ -47,20 +65,28 @@ contract InboxMock { emit InboxRetryableTicket(msg.sender, to, l2CallValue, gasLimit, data); return 0; } +} - function bridge() external view returns (IBridge) { - return IBridge(address(this)); - } - - function activeOutbox() external view returns (address) { - return address(this); - } - - function setL2ToL1Sender(address sender) external { - l2ToL1SenderMock = sender; - } +contract ERC20InboxMock is AbsInboxMock { + function createRetryableTicket( + address to, + uint256 l2CallValue, + uint256 maxSubmissionCost, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, + uint256 tokenTotalFeeAmount, + bytes calldata data + ) external returns (uint256) { + // ensure the user's deposit alone will make submission succeed + if (tokenTotalFeeAmount < (maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas)) { + revert("WRONG_TOKEN_VALUE"); + } - function l2ToL1Sender() external view returns (address) { - return l2ToL1SenderMock; + emit TicketData(maxSubmissionCost); + emit RefundAddresses(excessFeeRefundAddress, callValueRefundAddress); + emit InboxRetryableTicket(msg.sender, to, l2CallValue, gasLimit, data); + return 0; } } From 265aa2ec47bfe41dac03293a3657ed5eb6e3b034 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Apr 2023 17:34:17 +0200 Subject: [PATCH 005/163] Implement token deposit for ERC20-based rollup, include Foundry test case --- .../ethereum/L1ArbitrumMessenger.sol | 73 +++++++++++++- .../ethereum/gateway/L1ArbitrumGateway.sol | 68 ++++++++++++- .../ethereum/gateway/L1OrbitERC20Gateway.sol | 81 ++++++++++++++++ contracts/tokenbridge/test/InboxMock.sol | 1 - test/foundry/L1OrbitERC20Gateway.t.sol | 97 +++++++++++++++++++ 5 files changed, 313 insertions(+), 7 deletions(-) create mode 100644 contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol create mode 100644 test/foundry/L1OrbitERC20Gateway.t.sol diff --git a/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol b/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol index 2ff577182d..e612eab277 100644 --- a/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol +++ b/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol @@ -94,12 +94,14 @@ abstract contract L1ArbitrumMessenger { uint256 _gasPriceBid, bytes memory _data ) internal returns (uint256) { - uint256 seqNum = IInbox(_inbox).createRetryableTicket{ value: _l1CallValue }( + uint256 seqNum = _createRetryable( + _inbox, _to, + _refundTo, + _user, + _l1CallValue, _l2CallValue, _maxSubmissionCost, - _refundTo, // only refund excess fee to the custom address - _user, // user can cancel the retryable and receive call value refund _maxGas, _gasPriceBid, _data @@ -146,4 +148,69 @@ abstract contract L1ArbitrumMessenger { require(l2ToL1Sender != address(0), "NO_SENDER"); return l2ToL1Sender; } + + /** + * @notice Calls inbox to create retryable ticket. Default implementation is for standard Eth-based rollup, but it can be overriden to create retryable in ERC20-based rollup. + * @param _inbox address of the rollup's inbox + * @param _to destination L2 contract address + * @param _refundTo refund address for excess fee + * @param _user refund address for callvalue + * @param _totalFeeAmount amount of fees to pay, in Eth or native token, for retryable's execution + * @param _l2CallValue call value for retryable L2 message + * @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee + * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution + * @param _gasPriceBid price bid for L2 execution + * @param _data ABI encoded data of L2 message + * @return unique message number of the retryable transaction + */ + function _createRetryable( + address _inbox, + address _to, + address _refundTo, + address _user, + uint256 _totalFeeAmount, + uint256 _l2CallValue, + uint256 _maxSubmissionCost, + uint256 _maxGas, + uint256 _gasPriceBid, + bytes memory _data + ) internal virtual returns (uint256) { + return + IEthInbox(_inbox).createRetryableTicket{ value: _totalFeeAmount }( + _to, + _l2CallValue, + _maxSubmissionCost, + _refundTo, + _user, + _gasPriceBid, + _data + ); + } +} + +interface IERC20Inbox { + function createRetryableTicket( + address to, + uint256 l2CallValue, + uint256 maxSubmissionCost, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, + uint256 tokenTotalFeeAmount, + bytes calldata data + ) external returns (uint256); +} + +interface IEthInbox { + function createRetryableTicket( + address to, + uint256 l2CallValue, + uint256 maxSubmissionCost, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, + bytes calldata data + ) external payable returns (uint256); } diff --git a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol index 3ac89dee43..3d56279297 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol @@ -253,6 +253,7 @@ abstract contract L1ArbitrumGateway is bytes memory extraData; { uint256 _maxSubmissionCost; + uint256 tokenTotalFeeAmount; if (super.isRouter(msg.sender)) { // router encoded (_from, extraData) = GatewayMessageHandler.parseFromRouterToGateway(_data); @@ -260,8 +261,9 @@ abstract contract L1ArbitrumGateway is _from = msg.sender; extraData = _data; } - // user encoded - (_maxSubmissionCost, extraData) = abi.decode(extraData, (uint256, bytes)); + // unpack user encoded data + (_maxSubmissionCost, tokenTotalFeeAmount, extraData) = _parseUserEncodedData(extraData); + // the inboundEscrowAndCall functionality has been disabled, so no data is allowed require(extraData.length == 0, "EXTRA_DATA_DISABLED"); @@ -274,13 +276,14 @@ abstract contract L1ArbitrumGateway is // we override the res field to save on the stack res = getOutboundCalldata(_l1Token, _from, _to, _amount, extraData); - seqNum = createOutboundTxCustomRefund( + seqNum = _initiateDeposit( _refundTo, _from, _amount, _maxGas, _gasPriceBid, _maxSubmissionCost, + tokenTotalFeeAmount, res ); } @@ -339,4 +342,63 @@ abstract contract L1ArbitrumGateway is interfaceId == this.outboundTransferCustomRefund.selector || super.supportsInterface(interfaceId); } + + /** + * @notice Parse data that was encoded by user and passed into the outbound TX entrypoint + * @dev In case of standard ETH-based rollup, format of encoded data is expected to be: + * - maxSubmissionCost (uint256) + * - callHookData (bytes) + * In case of ERC20-based rollup, format of encoded data is expected to be: + * - maxSubmissionCost (uint256) + * - tokenTotalFeeAmount (uint256) + * - callHookData (bytes) + * @param data data encoded by user + * @return maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee + * @return tokenTotalFeeAmount Amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups, otherwise 0) + * @return callHookData Calldata for extra call in inboundEscrowAndCall on L2 + */ + function _parseUserEncodedData( + bytes memory data + ) + internal + pure + virtual + returns (uint256 maxSubmissionCost, uint256 tokenTotalFeeAmount, bytes memory callHookData) + { + (maxSubmissionCost, callHookData) = abi.decode(data, (uint256, bytes)); + } + + /** + * @notice Intermediate internal function that passes on parameters needed to trigger creation of retryable ticket. + * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2 + * @param _from Initiator of deposit + * @param _amount Token of token being deposited + * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution + * @param _gasPriceBid Gas price for L2 execution + * @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee + * //param tokenTotalFeeAmount Amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups) + * @param _data encoded data from router and user + * @return res abi encoded inbox sequence number + */ + function _initiateDeposit( + address _refundTo, + address _from, + uint256 _amount, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256, // tokenTotalFeeAmount + bytes memory _data + ) internal virtual returns (uint256) { + return + createOutboundTxCustomRefund( + _refundTo, + _from, + _amount, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + _data + ); + } } diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol new file mode 100644 index 0000000000..2a35dd7dbf --- /dev/null +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.6.11; + +import "./L1ERC20Gateway.sol"; +import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; + +/** + * @title Layer 1 Gateway contract for bridging standard ERC20s in ERC20-based rollup + * @notice This contract handles token deposits, holds the escrowed tokens on layer 1, and (ultimately) finalizes withdrawals. + * @dev Any ERC20 that requires non-standard functionality should use a separate gateway. + * Messages to layer 2 use the inbox's createRetryableTicket method. + */ +contract L1OrbitERC20Gateway is L1ERC20Gateway { + function _parseUserEncodedData( + bytes memory data + ) + internal + pure + override + returns (uint256 maxSubmissionCost, uint256 tokenTotalFeeAmount, bytes memory callHookData) + { + (maxSubmissionCost, tokenTotalFeeAmount, callHookData) = abi.decode( + data, + (uint256, uint256, bytes) + ); + } + + function _initiateDeposit( + address _refundTo, + address _from, + uint256, + 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) { + return + IERC20Inbox(_inbox).createRetryableTicket( + _to, + _l2CallValue, + _maxSubmissionCost, + _refundTo, + _user, + _maxGas, + _gasPriceBid, + _totalFeeAmount, + _data + ); + } +} diff --git a/contracts/tokenbridge/test/InboxMock.sol b/contracts/tokenbridge/test/InboxMock.sol index abb400e90d..a975041dc1 100644 --- a/contracts/tokenbridge/test/InboxMock.sol +++ b/contracts/tokenbridge/test/InboxMock.sol @@ -20,7 +20,6 @@ pragma solidity ^0.6.11; import "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import "@arbitrum/nitro-contracts/src/bridge/IBridge.sol"; -import "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; abstract contract AbsInboxMock { address l2ToL1SenderMock = address(0); diff --git a/test/foundry/L1OrbitERC20Gateway.t.sol b/test/foundry/L1OrbitERC20Gateway.t.sol new file mode 100644 index 0000000000..6620d2b3f9 --- /dev/null +++ b/test/foundry/L1OrbitERC20Gateway.t.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity 0.6.11; +pragma experimental ABIEncoderV2; + +import "forge-std/Test.sol"; +import "contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol"; +import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; +import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract L1OrbitERC20GatewayTest is Test { + L1OrbitERC20Gateway public l1Gateway; + IERC20 public token; + + // gateway params + address public l2Gateway = address(1000); + address public router = address(1001); + address public inbox = address(new ERC20InboxMock()); + address public l2BeaconProxyFactory = address(1003); + bytes32 public cloneableProxyHash = + 0x0000000000000000000000000000000000000000000000000000000000000001; + + address public user = address(1004); + + function setUp() public { + l1Gateway = new L1OrbitERC20Gateway(); + l1Gateway.initialize(l2Gateway, router, inbox, cloneableProxyHash, l2BeaconProxyFactory); + + token = IERC20(address(new TestERC20())); + + // fund user and router + vm.prank(user); + TestERC20(address(token)).mint(); + vm.deal(router, 100 ether); + } + + /* solhint-disable func-name-mixedcase */ + function test_initialize() public { + assertEq(l1Gateway.counterpartGateway(), l2Gateway, "Invalid counterpartGateway"); + assertEq(l1Gateway.router(), router, "Invalid router"); + assertEq(l1Gateway.inbox(), inbox, "Invalid inbox"); + assertEq( + l1Gateway.l2BeaconProxyFactory(), + l2BeaconProxyFactory, + "Invalid l2BeaconProxyFactory" + ); + assertEq(l1Gateway.whitelist(), address(0), "Invalid whitelist"); + } + + function test_outboundTransfer() public { + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + // retryable params + uint256 maxSubmissionCost = 0; + uint256 maxGas = 1000000000; + uint256 gasPrice = 3; + + uint256 depositAmount = 300; + uint256 nativeTokenTotalFee = maxGas * gasPrice; + + bytes memory callHookData = ""; + bytes memory userEncodedData = abi.encode( + maxSubmissionCost, + nativeTokenTotalFee, + callHookData + ); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); + + // approve token + vm.prank(user); + token.approve(address(l1Gateway), depositAmount); + + vm.prank(router); + l1Gateway.outboundTransfer( + address(token), + user, + depositAmount, + maxGas, + gasPrice, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + } +} From 98cbd9ff15e825e5408b742728c40a909bf41461 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Apr 2023 17:41:33 +0200 Subject: [PATCH 006/163] Add missing param --- contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol b/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol index e612eab277..9db41019d0 100644 --- a/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol +++ b/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol @@ -182,6 +182,7 @@ abstract contract L1ArbitrumMessenger { _maxSubmissionCost, _refundTo, _user, + _maxGas, _gasPriceBid, _data ); From cccd15606ee67ab24758e4684520f6bc97292ea6 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Apr 2023 17:54:40 +0200 Subject: [PATCH 007/163] Run tests as Github actions --- .github/build-test.yml | 50 +++++++++++++++++++ foundry.toml | 2 +- package.json | 1 + .../L1ERC20Gateway.t.sol | 0 .../L1OrbitERC20Gateway.t.sol | 0 5 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 .github/build-test.yml rename {test/foundry => test-foundry}/L1ERC20Gateway.t.sol (100%) rename {test/foundry => test-foundry}/L1OrbitERC20Gateway.t.sol (100%) diff --git a/.github/build-test.yml b/.github/build-test.yml new file mode 100644 index 0000000000..01d51cb5c5 --- /dev/null +++ b/.github/build-test.yml @@ -0,0 +1,50 @@ +on: [pull_request] + +name: Build and test + +jobs: + test-unit: + name: Test unit + runs-on: ubuntu-latest + steps: + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: nightly + + - name: Install packages + run: yarn + + - name: Run tests + run: yarn test:unit + + test-only-doesnt-exist: + name: No .only + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Check if .only exists in integration test + run: fgrep .only -R test/ && exit 1 || exit 0 + + test-hardhat: + name: Test hardhat + runs-on: ubuntu-latest + steps: + - name: Setup node/yarn + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'yarn' + cache-dependency-path: '**/yarn.lock' + + - name: Install packages + run: yarn + + - name: Compile contracts + run: yarn build + + - name: Run integration tests + run: yarn test diff --git a/foundry.toml b/foundry.toml index 922e8d94a2..f2022611da 100644 --- a/foundry.toml +++ b/foundry.toml @@ -2,7 +2,7 @@ src = 'contracts' out = 'out' libs = ["node_modules", "lib"] -test = 'test/foundry' +test = 'test-foundry' cache_path = 'forge-cache' optimizer = true optimizer_runs = 20000 diff --git a/package.json b/package.json index a50da4e38d..c505e8b90c 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "test:e2e": "hardhat test test/*.e2e.ts", "test:l1": "hardhat test test/*.l1.ts", "test:l2": "hardhat test test/*.l2.ts", + "test:unit": "forge test", "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", diff --git a/test/foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol similarity index 100% rename from test/foundry/L1ERC20Gateway.t.sol rename to test-foundry/L1ERC20Gateway.t.sol diff --git a/test/foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol similarity index 100% rename from test/foundry/L1OrbitERC20Gateway.t.sol rename to test-foundry/L1OrbitERC20Gateway.t.sol From 33e395ca9822a25d76bb6e0e0ead94b4a38c3eec Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Apr 2023 17:57:22 +0200 Subject: [PATCH 008/163] Remove circleci config --- .circleci/config.yml | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 5c293bcd8a..0000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,22 +0,0 @@ -version: 2.1 -executors: - general-test-executor: - docker: - - image: cimg/node:16.18 - -jobs: - contract-test: - executor: general-test-executor - working_directory: ~/token-bridge-contracts - steps: - - checkout - - run: fgrep .only -R test/ && exit 1 || exit 0 - - run: | - yarn install - yarn build - yarn test - -workflows: - build-test-workflow: - jobs: - - contract-test From 72e3626e43ea1b2e8ee131fa3c68730962910aa9 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Apr 2023 18:01:24 +0200 Subject: [PATCH 009/163] Put workflow file in the right place --- .github/{ => workflows}/build-test.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{ => workflows}/build-test.yml (100%) diff --git a/.github/build-test.yml b/.github/workflows/build-test.yml similarity index 100% rename from .github/build-test.yml rename to .github/workflows/build-test.yml From d5f916ea3802f4efcc3d437dcbc24ec222023b01 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Apr 2023 18:09:11 +0200 Subject: [PATCH 010/163] Reconfigure CI triggers --- .github/workflows/build-test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 01d51cb5c5..ee8db995bd 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,4 +1,6 @@ -on: [pull_request] +on: + pull_request: + types: [opened, synchronize] name: Build and test From 792483c7a6a5dfd1b211992a42f2cd7e2f932fe8 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Apr 2023 12:02:09 +0200 Subject: [PATCH 011/163] Check DepositInitiated is correctly emitted --- .github/workflows/build-test.yml | 6 ++++-- test-foundry/L1ERC20Gateway.t.sol | 16 ++++++++++++++++ test-foundry/L1OrbitERC20Gateway.t.sol | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index ee8db995bd..24fe3c4e62 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,8 +1,10 @@ +name: Build and test + on: + workflow_dispatch: pull_request: types: [opened, synchronize] - -name: Build and test + push: jobs: test-unit: diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index bb1d7d8e30..af9f2ea31a 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -66,6 +66,11 @@ contract L1ERC20GatewayTest is Test { vm.prank(user); token.approve(address(l1Gateway), depositAmount); + // expect event + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(token), user, user, 0, depositAmount); + + // trigger deposit vm.prank(router); l1Gateway.outboundTransfer{ value: maxSubmissionCost + maxGas * gasPrice }( address(token), @@ -87,4 +92,15 @@ contract L1ERC20GatewayTest is Test { "Wrong l1 gateway balance" ); } + + //// + // Event declarations + //// + event DepositInitiated( + address l1Token, + address indexed _from, + address indexed _to, + uint256 indexed _sequenceNumber, + uint256 _amount + ); } diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 6620d2b3f9..c2a2e0fe16 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -73,6 +73,11 @@ contract L1OrbitERC20GatewayTest is Test { vm.prank(user); token.approve(address(l1Gateway), depositAmount); + // expect event + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(token), user, user, 0, depositAmount); + + // trigger deposit vm.prank(router); l1Gateway.outboundTransfer( address(token), @@ -94,4 +99,15 @@ contract L1OrbitERC20GatewayTest is Test { "Wrong l1 gateway balance" ); } + + //// + // Event declarations + //// + event DepositInitiated( + address l1Token, + address indexed _from, + address indexed _to, + uint256 indexed _sequenceNumber, + uint256 _amount + ); } From 92a68109ddf5c5b5d6dc4b3f179193cb7f1116fb Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Apr 2023 12:58:02 +0200 Subject: [PATCH 012/163] Add more event checks --- test-foundry/L1ERC20Gateway.t.sol | 10 +++++++++- test-foundry/L1OrbitERC20Gateway.t.sol | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index af9f2ea31a..f50f9f3532 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -66,7 +66,13 @@ contract L1ERC20GatewayTest is Test { vm.prank(user); token.approve(address(l1Gateway), depositAmount); - // expect event + // 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 DepositInitiated(address(token), user, user, 0, depositAmount); @@ -103,4 +109,6 @@ contract L1ERC20GatewayTest is Test { uint256 indexed _sequenceNumber, uint256 _amount ); + event TicketData(uint256 maxSubmissionCost); + event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); } diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index c2a2e0fe16..e53a3efd36 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -73,7 +73,13 @@ contract L1OrbitERC20GatewayTest is Test { vm.prank(user); token.approve(address(l1Gateway), depositAmount); - // expect event + // expect events + 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 DepositInitiated(address(token), user, user, 0, depositAmount); @@ -110,4 +116,6 @@ contract L1OrbitERC20GatewayTest is Test { uint256 indexed _sequenceNumber, uint256 _amount ); + event TicketData(uint256 maxSubmissionCost); + event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); } From 8354537fea0dbdd4c755439a205d3dfe86829f44 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Apr 2023 13:54:45 +0200 Subject: [PATCH 013/163] Use IL1ArbitrumGateway interface where possible --- test-foundry/L1ERC20Gateway.t.sol | 22 +++++++++++++++------ test-foundry/L1OrbitERC20Gateway.t.sol | 27 ++++++++++++++++++++------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index f50f9f3532..67a3313e3b 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -10,7 +10,7 @@ import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract L1ERC20GatewayTest is Test { - L1ERC20Gateway public l1Gateway; + IL1ArbitrumGateway public l1Gateway; IERC20 public token; // gateway params @@ -25,7 +25,13 @@ contract L1ERC20GatewayTest is Test { function setUp() public { l1Gateway = new L1ERC20Gateway(); - l1Gateway.initialize(l2Gateway, router, inbox, cloneableProxyHash, l2BeaconProxyFactory); + L1ERC20Gateway(address(l1Gateway)).initialize( + l2Gateway, + router, + inbox, + cloneableProxyHash, + l2BeaconProxyFactory + ); token = IERC20(address(new TestERC20())); @@ -37,15 +43,19 @@ contract L1ERC20GatewayTest is Test { /* solhint-disable func-name-mixedcase */ function test_initialize() public { - assertEq(l1Gateway.counterpartGateway(), l2Gateway, "Invalid counterpartGateway"); - assertEq(l1Gateway.router(), router, "Invalid router"); + assertEq( + L1ERC20Gateway(address(l1Gateway)).counterpartGateway(), + l2Gateway, + "Invalid counterpartGateway" + ); + assertEq(L1ERC20Gateway(address(l1Gateway)).router(), router, "Invalid router"); assertEq(l1Gateway.inbox(), inbox, "Invalid inbox"); assertEq( - l1Gateway.l2BeaconProxyFactory(), + L1ERC20Gateway(address(l1Gateway)).l2BeaconProxyFactory(), l2BeaconProxyFactory, "Invalid l2BeaconProxyFactory" ); - assertEq(l1Gateway.whitelist(), address(0), "Invalid whitelist"); + assertEq(L1ERC20Gateway(address(l1Gateway)).whitelist(), address(0), "Invalid whitelist"); } function test_outboundTransfer() public { diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index e53a3efd36..c85d6e4fec 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -5,12 +5,13 @@ pragma experimental ABIEncoderV2; import "forge-std/Test.sol"; import "contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol"; + import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract L1OrbitERC20GatewayTest is Test { - L1OrbitERC20Gateway public l1Gateway; + IL1ArbitrumGateway public l1Gateway; IERC20 public token; // gateway params @@ -25,7 +26,13 @@ contract L1OrbitERC20GatewayTest is Test { function setUp() public { l1Gateway = new L1OrbitERC20Gateway(); - l1Gateway.initialize(l2Gateway, router, inbox, cloneableProxyHash, l2BeaconProxyFactory); + L1OrbitERC20Gateway(address(l1Gateway)).initialize( + l2Gateway, + router, + inbox, + cloneableProxyHash, + l2BeaconProxyFactory + ); token = IERC20(address(new TestERC20())); @@ -37,15 +44,23 @@ contract L1OrbitERC20GatewayTest is Test { /* solhint-disable func-name-mixedcase */ function test_initialize() public { - assertEq(l1Gateway.counterpartGateway(), l2Gateway, "Invalid counterpartGateway"); - assertEq(l1Gateway.router(), router, "Invalid router"); + assertEq( + L1OrbitERC20Gateway(address(l1Gateway)).counterpartGateway(), + l2Gateway, + "Invalid counterpartGateway" + ); + assertEq(L1OrbitERC20Gateway(address(l1Gateway)).router(), router, "Invalid router"); assertEq(l1Gateway.inbox(), inbox, "Invalid inbox"); assertEq( - l1Gateway.l2BeaconProxyFactory(), + L1OrbitERC20Gateway(address(l1Gateway)).l2BeaconProxyFactory(), l2BeaconProxyFactory, "Invalid l2BeaconProxyFactory" ); - assertEq(l1Gateway.whitelist(), address(0), "Invalid whitelist"); + assertEq( + L1OrbitERC20Gateway(address(l1Gateway)).whitelist(), + address(0), + "Invalid whitelist" + ); } function test_outboundTransfer() public { From bbdbda1e1c227c582a21a04fe19ad95f3fc998a3 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Apr 2023 14:08:04 +0200 Subject: [PATCH 014/163] Test outboundTransferCustomRefund --- test-foundry/L1ERC20Gateway.t.sol | 53 +++++++++++++++++++++++ test-foundry/L1OrbitERC20Gateway.t.sol | 60 ++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 67a3313e3b..6f0146b890 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -109,6 +109,59 @@ contract L1ERC20GatewayTest is Test { ); } + function test_outboundTransferCustomRefund() public { + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + // retryable params + uint256 maxSubmissionCost = 1; + uint256 maxGas = 2000000000; + uint256 gasPrice = 7; + uint256 depositAmount = 450; + address refundTo = address(2000); + bytes memory callHookData = ""; + bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); + + // approve token + vm.prank(user); + token.approve(address(l1Gateway), depositAmount); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(refundTo, user); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(token), user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + l1Gateway.outboundTransferCustomRefund{ value: maxSubmissionCost + maxGas * gasPrice }( + address(token), + refundTo, + user, + depositAmount, + maxGas, + gasPrice, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + } + //// // Event declarations //// diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index c85d6e4fec..2ce8af7ae6 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -121,6 +121,66 @@ contract L1OrbitERC20GatewayTest is Test { ); } + function test_outboundTransferCustomRefund() public { + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + // retryable params + uint256 maxSubmissionCost = 0; + uint256 maxGas = 200000000; + uint256 gasPrice = 4; + + uint256 depositAmount = 700; + uint256 nativeTokenTotalFee = maxGas * gasPrice; + address refundTo = address(3000); + + bytes memory callHookData = ""; + bytes memory userEncodedData = abi.encode( + maxSubmissionCost, + nativeTokenTotalFee, + callHookData + ); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); + + // approve token + vm.prank(user); + token.approve(address(l1Gateway), depositAmount); + + // expect events + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(refundTo, user); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(token), user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + l1Gateway.outboundTransferCustomRefund( + address(token), + refundTo, + user, + depositAmount, + maxGas, + gasPrice, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + } + //// // Event declarations //// From 2c1a092e3b6f287c90613b42d837da08cb21bb18 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Apr 2023 16:58:24 +0200 Subject: [PATCH 015/163] Test finalizeInboundTransfer --- test-foundry/L1ERC20Gateway.t.sol | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 6f0146b890..5842f73a8f 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -162,6 +162,40 @@ contract L1ERC20GatewayTest is Test { ); } + function test_finalizeInboundTransfer() public { + // fund gateway with tokens being withdrawn + vm.prank(address(l1Gateway)); + TestERC20(address(token)).mint(); + + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + // withdrawal params + address from = address(3000); + uint256 withdrawalAmount = 25; + 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(address(token), from, user, withdrawalAmount, data); + + // check tokens are properly released + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceAfter - userBalanceBefore, withdrawalAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceBefore - l1GatewayBalanceAfter, + withdrawalAmount, + "Wrong l1 gateway balance" + ); + } + //// // Event declarations //// From 26d4cc8fad70d12c01327d229e77b31181f4d311 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 11 Apr 2023 16:29:06 +0200 Subject: [PATCH 016/163] Make L1OrbitERC20GatewayTest inherit from L1ERC20GatewayTest to avoid code duplication --- test-foundry/L1ERC20Gateway.t.sol | 10 +++-- test-foundry/L1OrbitERC20Gateway.t.sol | 57 +++----------------------- 2 files changed, 12 insertions(+), 55 deletions(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 5842f73a8f..c45553e010 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -16,14 +16,16 @@ contract L1ERC20GatewayTest is Test { // gateway params address public l2Gateway = address(1000); address public router = address(1001); - address public inbox = address(new InboxMock()); + address public inbox; address public l2BeaconProxyFactory = address(1003); bytes32 public cloneableProxyHash = 0x0000000000000000000000000000000000000000000000000000000000000001; address public user = address(1004); - function setUp() public { + function setUp() public virtual { + inbox = address(new InboxMock()); + l1Gateway = new L1ERC20Gateway(); L1ERC20Gateway(address(l1Gateway)).initialize( l2Gateway, @@ -58,7 +60,7 @@ contract L1ERC20GatewayTest is Test { assertEq(L1ERC20Gateway(address(l1Gateway)).whitelist(), address(0), "Invalid whitelist"); } - function test_outboundTransfer() public { + function test_outboundTransfer() public virtual { // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); @@ -109,7 +111,7 @@ contract L1ERC20GatewayTest is Test { ); } - function test_outboundTransferCustomRefund() public { + function test_outboundTransferCustomRefund() public virtual { // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 2ce8af7ae6..68c5a30d12 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -3,28 +3,16 @@ pragma solidity 0.6.11; pragma experimental ABIEncoderV2; -import "forge-std/Test.sol"; +import { L1ERC20GatewayTest } from "./L1ERC20Gateway.t.sol"; import "contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol"; import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -contract L1OrbitERC20GatewayTest is Test { - IL1ArbitrumGateway public l1Gateway; - IERC20 public token; +contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { + function setUp() public override { + inbox = address(new ERC20InboxMock()); - // gateway params - address public l2Gateway = address(1000); - address public router = address(1001); - address public inbox = address(new ERC20InboxMock()); - address public l2BeaconProxyFactory = address(1003); - bytes32 public cloneableProxyHash = - 0x0000000000000000000000000000000000000000000000000000000000000001; - - address public user = address(1004); - - function setUp() public { l1Gateway = new L1OrbitERC20Gateway(); L1OrbitERC20Gateway(address(l1Gateway)).initialize( l2Gateway, @@ -43,27 +31,7 @@ contract L1OrbitERC20GatewayTest is Test { } /* solhint-disable func-name-mixedcase */ - function test_initialize() public { - assertEq( - L1OrbitERC20Gateway(address(l1Gateway)).counterpartGateway(), - l2Gateway, - "Invalid counterpartGateway" - ); - assertEq(L1OrbitERC20Gateway(address(l1Gateway)).router(), router, "Invalid router"); - assertEq(l1Gateway.inbox(), inbox, "Invalid inbox"); - assertEq( - L1OrbitERC20Gateway(address(l1Gateway)).l2BeaconProxyFactory(), - l2BeaconProxyFactory, - "Invalid l2BeaconProxyFactory" - ); - assertEq( - L1OrbitERC20Gateway(address(l1Gateway)).whitelist(), - address(0), - "Invalid whitelist" - ); - } - - function test_outboundTransfer() public { + function test_outboundTransfer() public override { // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); @@ -121,7 +89,7 @@ contract L1OrbitERC20GatewayTest is Test { ); } - function test_outboundTransferCustomRefund() public { + function test_outboundTransferCustomRefund() public override { // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); @@ -180,17 +148,4 @@ contract L1OrbitERC20GatewayTest is Test { "Wrong l1 gateway balance" ); } - - //// - // Event declarations - //// - event DepositInitiated( - address l1Token, - address indexed _from, - address indexed _to, - uint256 indexed _sequenceNumber, - uint256 _amount - ); - event TicketData(uint256 maxSubmissionCost); - event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); } From 9fb72cd43d48d7d1b011e42c14cdfe5b54808987 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 11 Apr 2023 17:04:16 +0200 Subject: [PATCH 017/163] Test failure conditions of outboundTransferCustomRefund --- test-foundry/L1ERC20Gateway.t.sol | 33 +++++++++++++++++++++++++- test-foundry/L1OrbitERC20Gateway.t.sol | 18 ++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index c45553e010..9def671920 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -117,7 +117,7 @@ contract L1ERC20GatewayTest is Test { uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); // retryable params - uint256 maxSubmissionCost = 1; + uint256 maxSubmissionCost = 2; uint256 maxGas = 2000000000; uint256 gasPrice = 7; uint256 depositAmount = 450; @@ -164,6 +164,37 @@ contract L1ERC20GatewayTest is Test { ); } + function test_outboundTransferCustomRefund_revert_NotFromRouter() public { + vm.expectRevert("NOT_FROM_ROUTER"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(token), + user, + user, + 400, + 0.1 ether, + 0.01 ether, + "" + ); + } + + function test_outboundTransferCustomRefund_revert_ExtraDataDisabled() public virtual { + bytes memory callHookData = abi.encodeWithSignature("doSomething()"); + bytes memory userEncodedData = abi.encode(2, callHookData); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); + + vm.prank(router); + vm.expectRevert("EXTRA_DATA_DISABLED"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(token), + user, + user, + 400, + 0.1 ether, + 0.01 ether, + routerEncodedData + ); + } + function test_finalizeInboundTransfer() public { // fund gateway with tokens being withdrawn vm.prank(address(l1Gateway)); diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 68c5a30d12..23cd5aa08c 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -148,4 +148,22 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { "Wrong l1 gateway balance" ); } + + function test_outboundTransferCustomRefund_revert_ExtraDataDisabled() public override { + bytes memory callHookData = abi.encodeWithSignature("doSomething()"); + bytes memory userEncodedData = abi.encode(5, 10, callHookData); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); + + vm.prank(router); + vm.expectRevert("EXTRA_DATA_DISABLED"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(token), + user, + user, + 400, + 0.1 ether, + 0.01 ether, + routerEncodedData + ); + } } From b9a819c860f1b20b3fcb413b294d537ef48786eb Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 11 Apr 2023 17:34:10 +0200 Subject: [PATCH 018/163] Dummy commit to trigger CI --- test-foundry/L1ERC20Gateway.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index f50f9f3532..ea0fb24cd3 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -99,7 +99,7 @@ contract L1ERC20GatewayTest is Test { ); } - //// + // // Event declarations //// event DepositInitiated( From f94013be44ab07aacb668189a246657a41f2d40e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 11 Apr 2023 18:09:47 +0200 Subject: [PATCH 019/163] Add tests for L1NotContract --- test-foundry/L1ERC20Gateway.t.sol | 16 ++++++++++++++++ test-foundry/L1OrbitERC20Gateway.t.sol | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 9def671920..1998685c15 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -195,6 +195,22 @@ contract L1ERC20GatewayTest is Test { ); } + function test_outboundTransferCustomRefund_revert_L1NotContract() public virtual { + address invalidTokenAddress = address(70); + + vm.prank(router); + vm.expectRevert("L1_NOT_CONTRACT"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(invalidTokenAddress), + user, + user, + 400, + 0.1 ether, + 0.01 ether, + abi.encode(user, abi.encode(2, "")) + ); + } + function test_finalizeInboundTransfer() public { // fund gateway with tokens being withdrawn vm.prank(address(l1Gateway)); diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 23cd5aa08c..15b4513ecf 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -166,4 +166,20 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { routerEncodedData ); } + + function test_outboundTransferCustomRefund_revert_L1NotContract() public override { + address invalidTokenAddress = address(70); + + vm.prank(router); + vm.expectRevert("L1_NOT_CONTRACT"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(invalidTokenAddress), + user, + user, + 400, + 0.1 ether, + 0.01 ether, + abi.encode(user, abi.encode(2, 3, "")) + ); + } } From 82361a59c2caf69e27ac3d431141acd91a227e2a Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 11 Apr 2023 18:19:12 +0200 Subject: [PATCH 020/163] Another one --- test-foundry/L1ERC20Gateway.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index ea0fb24cd3..f50f9f3532 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -99,7 +99,7 @@ contract L1ERC20GatewayTest is Test { ); } - // + //// // Event declarations //// event DepositInitiated( From b928f79bd57db85671c4097be30d122283cd8ce4 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 11 Apr 2023 18:32:48 +0200 Subject: [PATCH 021/163] Add missing steps --- .github/workflows/build-test.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 24fe3c4e62..7593ac32c4 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -11,11 +11,22 @@ jobs: name: Test unit runs-on: ubuntu-latest steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: version: nightly + - name: Setup node/yarn + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'yarn' + cache-dependency-path: '**/yarn.lock' + - name: Install packages run: yarn @@ -37,6 +48,10 @@ jobs: name: Test hardhat runs-on: ubuntu-latest steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Setup node/yarn uses: actions/setup-node@v3 with: From 5281ee4861174fed97d21aefade194a3444596fe Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 12 Apr 2023 11:29:18 +0200 Subject: [PATCH 022/163] Reuse buildRouterEncodedData function in test to avoid test duplication --- test-foundry/L1ERC20Gateway.t.sol | 19 ++++++++++-- test-foundry/L1OrbitERC20Gateway.t.sol | 43 +++++++++----------------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 1998685c15..3ae6b82abc 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -179,8 +179,7 @@ contract L1ERC20GatewayTest is Test { function test_outboundTransferCustomRefund_revert_ExtraDataDisabled() public virtual { bytes memory callHookData = abi.encodeWithSignature("doSomething()"); - bytes memory userEncodedData = abi.encode(2, callHookData); - bytes memory routerEncodedData = abi.encode(user, userEncodedData); + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); vm.prank(router); vm.expectRevert("EXTRA_DATA_DISABLED"); @@ -207,7 +206,7 @@ contract L1ERC20GatewayTest is Test { 400, 0.1 ether, 0.01 ether, - abi.encode(user, abi.encode(2, "")) + buildRouterEncodedData("") ); } @@ -245,6 +244,20 @@ contract L1ERC20GatewayTest is Test { ); } + //// + // Helper functions + //// + function buildRouterEncodedData( + bytes memory callHookData + ) internal view virtual returns (bytes memory) { + uint256 maxSubmissionCost = 20; + + bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); + + return routerEncodedData; + } + //// // Event declarations //// diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 15b4513ecf..9b05d3278b 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -149,37 +149,22 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { ); } - function test_outboundTransferCustomRefund_revert_ExtraDataDisabled() public override { - bytes memory callHookData = abi.encodeWithSignature("doSomething()"); - bytes memory userEncodedData = abi.encode(5, 10, callHookData); - bytes memory routerEncodedData = abi.encode(user, userEncodedData); + //// + // Helper functions + //// + function buildRouterEncodedData( + bytes memory callHookData + ) internal view override returns (bytes memory) { + uint256 nativeTokenTotalFee = 350; + uint256 maxSubmissionCost = 20; - vm.prank(router); - vm.expectRevert("EXTRA_DATA_DISABLED"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( - address(token), - user, - user, - 400, - 0.1 ether, - 0.01 ether, - routerEncodedData + bytes memory userEncodedData = abi.encode( + maxSubmissionCost, + nativeTokenTotalFee, + callHookData ); - } - - function test_outboundTransferCustomRefund_revert_L1NotContract() public override { - address invalidTokenAddress = address(70); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); - vm.prank(router); - vm.expectRevert("L1_NOT_CONTRACT"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( - address(invalidTokenAddress), - user, - user, - 400, - 0.1 ether, - 0.01 ether, - abi.encode(user, abi.encode(2, 3, "")) - ); + return routerEncodedData; } } From 54cb935c19006da4ec07660309ccc4b763299a4d Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 12 Apr 2023 13:03:12 +0200 Subject: [PATCH 023/163] Test getOutboundCalldata --- test-foundry/L1ERC20Gateway.t.sol | 56 +++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 3ae6b82abc..a6558216bb 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -177,7 +177,7 @@ contract L1ERC20GatewayTest is Test { ); } - function test_outboundTransferCustomRefund_revert_ExtraDataDisabled() public virtual { + function test_outboundTransferCustomRefund_revert_ExtraDataDisabled() public { bytes memory callHookData = abi.encodeWithSignature("doSomething()"); bytes memory routerEncodedData = buildRouterEncodedData(callHookData); @@ -194,7 +194,7 @@ contract L1ERC20GatewayTest is Test { ); } - function test_outboundTransferCustomRefund_revert_L1NotContract() public virtual { + function test_outboundTransferCustomRefund_revert_L1NotContract() public { address invalidTokenAddress = address(70); vm.prank(router); @@ -210,6 +210,22 @@ contract L1ERC20GatewayTest is Test { ); } + function test_outboundTransferCustomRefund_revert_AmountExceedsAllowance() public { + uint256 tooManyTokens = 500 ether; + + vm.prank(router); + vm.expectRevert("ERC20: transfer amount exceeds balance"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(token), + user, + user, + tooManyTokens, + 0.1 ether, + 0.01 ether, + buildRouterEncodedData("") + ); + } + function test_finalizeInboundTransfer() public { // fund gateway with tokens being withdrawn vm.prank(address(l1Gateway)); @@ -244,6 +260,42 @@ contract L1ERC20GatewayTest is Test { ); } + function test_getOutboundCalldata() public { + bytes memory outboundCalldata = l1Gateway.getOutboundCalldata({ + _token: address(token), + _from: user, + _to: address(800), + _amount: 355, + _data: abi.encode("doStuff()") + }); + + bytes memory expectedCalldata = abi.encodeWithSelector( + ITokenGateway.finalizeInboundTransfer.selector, + address(token), + user, + address(800), + 355, + abi.encode( + abi.encode(abi.encode("IntArbTestToken"), abi.encode("IARB"), abi.encode(18)), + abi.encode("doStuff()") + ) + ); + + assertEq(outboundCalldata, expectedCalldata, "Invalid outboundCalldata"); + } + + function callStatic( + address targetContract, + bytes4 targetFunction + ) internal view returns (bytes memory) { + ( + , + /* bool success */ + bytes memory res + ) = targetContract.staticcall(abi.encodeWithSelector(targetFunction)); + return res; + } + //// // Helper functions //// From 0f3f56ec67750d5db058b2cd3d5899ba44d8cee7 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 12 Apr 2023 15:04:35 +0200 Subject: [PATCH 024/163] Test supportsInterface --- test-foundry/L1ERC20Gateway.t.sol | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index a6558216bb..27b6b7dbb6 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -284,16 +284,16 @@ contract L1ERC20GatewayTest is Test { assertEq(outboundCalldata, expectedCalldata, "Invalid outboundCalldata"); } - function callStatic( - address targetContract, - bytes4 targetFunction - ) internal view returns (bytes memory) { - ( - , - /* bool success */ - bytes memory res - ) = targetContract.staticcall(abi.encodeWithSelector(targetFunction)); - return res; + function test_supportsInterface(bytes4 iface) public { + bool expected = false; + if ( + iface == type(IERC165).interfaceId || + iface == IL1ArbitrumGateway.outboundTransferCustomRefund.selector + ) { + expected = true; + } + + assertEq(l1Gateway.supportsInterface(iface), expected, "Interface shouldn't be supported"); } //// From fb97ab55fce4030714df4b50794dfa8da25621fd Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 12 Apr 2023 15:29:45 +0200 Subject: [PATCH 025/163] test encodeWithdrawal --- test-foundry/L1ERC20Gateway.t.sol | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 27b6b7dbb6..a8d3a774e9 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -296,6 +296,16 @@ contract L1ERC20GatewayTest is Test { assertEq(l1Gateway.supportsInterface(iface), expected, "Interface shouldn't be supported"); } + function test_encodeWithdrawal(uint256 exitNum, address dest) public { + bytes32 encodedWithdrawal = L1ERC20Gateway(address(l1Gateway)).encodeWithdrawal( + exitNum, + dest + ); + bytes32 expectedEncoding = keccak256(abi.encode(exitNum, dest)); + + assertEq(encodedWithdrawal, expectedEncoding, "Invalid encodeWithdrawal"); + } + //// // Helper functions //// From ef122bfd1c01c98b47c39ad2ded6f09cc21f09ed Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 12 Apr 2023 15:51:28 +0200 Subject: [PATCH 026/163] Test reverts in initializer --- test-foundry/L1ERC20Gateway.t.sol | 39 +++++++++++++++++--------- test-foundry/L1OrbitERC20Gateway.t.sol | 11 ++++++++ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index a8d3a774e9..40f0ff8878 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -44,20 +44,31 @@ contract L1ERC20GatewayTest is Test { } /* solhint-disable func-name-mixedcase */ - function test_initialize() public { - assertEq( - L1ERC20Gateway(address(l1Gateway)).counterpartGateway(), - l2Gateway, - "Invalid counterpartGateway" - ); - assertEq(L1ERC20Gateway(address(l1Gateway)).router(), router, "Invalid router"); - assertEq(l1Gateway.inbox(), inbox, "Invalid inbox"); - assertEq( - L1ERC20Gateway(address(l1Gateway)).l2BeaconProxyFactory(), - l2BeaconProxyFactory, - "Invalid l2BeaconProxyFactory" - ); - assertEq(L1ERC20Gateway(address(l1Gateway)).whitelist(), address(0), "Invalid whitelist"); + function test_initialize() public virtual { + L1ERC20Gateway gateway = new L1ERC20Gateway(); + gateway.initialize(l2Gateway, router, inbox, cloneableProxyHash, l2BeaconProxyFactory); + + assertEq(gateway.counterpartGateway(), l2Gateway, "Invalid counterpartGateway"); + assertEq(gateway.router(), router, "Invalid router"); + assertEq(gateway.inbox(), inbox, "Invalid inbox"); + assertEq(gateway.l2BeaconProxyFactory(), l2BeaconProxyFactory, "Invalid beacon"); + assertEq(gateway.whitelist(), address(0), "Invalid whitelist"); + } + + function test_initialize_revert_InvalidProxyHash() public { + L1ERC20Gateway gateway = new L1ERC20Gateway(); + bytes32 invalidProxyHash = bytes32(0); + + vm.expectRevert("INVALID_PROXYHASH"); + gateway.initialize(l2Gateway, router, inbox, invalidProxyHash, l2BeaconProxyFactory); + } + + function test_initialize_revert_InvalidBeacon() public { + L1ERC20Gateway gateway = new L1ERC20Gateway(); + address invalidBeaconProxyFactory = address(0); + + vm.expectRevert("INVALID_BEACON"); + gateway.initialize(l2Gateway, router, inbox, cloneableProxyHash, invalidBeaconProxyFactory); } function test_outboundTransfer() public virtual { diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 9b05d3278b..8441c446ac 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -31,6 +31,17 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { } /* solhint-disable func-name-mixedcase */ + function test_initialize() public override { + L1ERC20Gateway gateway = new L1OrbitERC20Gateway(); + gateway.initialize(l2Gateway, router, inbox, cloneableProxyHash, l2BeaconProxyFactory); + + assertEq(gateway.counterpartGateway(), l2Gateway, "Invalid counterpartGateway"); + assertEq(gateway.router(), router, "Invalid router"); + assertEq(gateway.inbox(), inbox, "Invalid inbox"); + assertEq(gateway.l2BeaconProxyFactory(), l2BeaconProxyFactory, "Invalid beacon"); + assertEq(gateway.whitelist(), address(0), "Invalid whitelist"); + } + function test_outboundTransfer() public override { // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); From ae2517e2150b02a5c266d9de1974a9ca29f23567 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 13 Apr 2023 11:27:22 +0200 Subject: [PATCH 027/163] Encode native token fee to the end of the user encoded message --- .../ethereum/gateway/L1ArbitrumGateway.sol | 6 ++--- .../ethereum/gateway/L1OrbitERC20Gateway.sol | 6 ++--- contracts/tokenbridge/test/InboxMock.sol | 20 +++++++++++++++- test-foundry/L1ERC20Gateway.t.sol | 10 ++++++++ test-foundry/L1OrbitERC20Gateway.t.sol | 24 +++++++++++++++++-- 5 files changed, 57 insertions(+), 9 deletions(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol index 3d56279297..847651644a 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol @@ -262,7 +262,7 @@ abstract contract L1ArbitrumGateway is extraData = _data; } // unpack user encoded data - (_maxSubmissionCost, tokenTotalFeeAmount, extraData) = _parseUserEncodedData(extraData); + (_maxSubmissionCost, extraData, tokenTotalFeeAmount) = _parseUserEncodedData(extraData); // the inboundEscrowAndCall functionality has been disabled, so no data is allowed require(extraData.length == 0, "EXTRA_DATA_DISABLED"); @@ -354,8 +354,8 @@ abstract contract L1ArbitrumGateway is * - callHookData (bytes) * @param data data encoded by user * @return maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee - * @return tokenTotalFeeAmount Amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups, otherwise 0) * @return callHookData Calldata for extra call in inboundEscrowAndCall on L2 + * @return tokenTotalFeeAmount Amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups, otherwise 0) */ function _parseUserEncodedData( bytes memory data @@ -363,7 +363,7 @@ abstract contract L1ArbitrumGateway is internal pure virtual - returns (uint256 maxSubmissionCost, uint256 tokenTotalFeeAmount, bytes memory callHookData) + returns (uint256 maxSubmissionCost, bytes memory callHookData, uint256 tokenTotalFeeAmount) { (maxSubmissionCost, callHookData) = abi.decode(data, (uint256, bytes)); } diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index 2a35dd7dbf..5b0cd65d67 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -18,11 +18,11 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { internal pure override - returns (uint256 maxSubmissionCost, uint256 tokenTotalFeeAmount, bytes memory callHookData) + returns (uint256 maxSubmissionCost, bytes memory callHookData, uint256 tokenTotalFeeAmount) { - (maxSubmissionCost, tokenTotalFeeAmount, callHookData) = abi.decode( + (maxSubmissionCost, callHookData, tokenTotalFeeAmount) = abi.decode( data, - (uint256, uint256, bytes) + (uint256, bytes, uint256) ); } diff --git a/contracts/tokenbridge/test/InboxMock.sol b/contracts/tokenbridge/test/InboxMock.sol index a975041dc1..562c2b3480 100644 --- a/contracts/tokenbridge/test/InboxMock.sol +++ b/contracts/tokenbridge/test/InboxMock.sol @@ -67,6 +67,16 @@ contract InboxMock is AbsInboxMock { } contract ERC20InboxMock is AbsInboxMock { + event ERC20InboxRetryableTicket( + address from, + address to, + uint256 l2CallValue, + uint256 maxGas, + uint256 gasPrice, + uint256 tokenTotalFeeAmount, + bytes data + ); + function createRetryableTicket( address to, uint256 l2CallValue, @@ -85,7 +95,15 @@ contract ERC20InboxMock is AbsInboxMock { emit TicketData(maxSubmissionCost); emit RefundAddresses(excessFeeRefundAddress, callValueRefundAddress); - emit InboxRetryableTicket(msg.sender, to, l2CallValue, gasLimit, data); + emit ERC20InboxRetryableTicket( + msg.sender, + to, + l2CallValue, + gasLimit, + maxFeePerGas, + tokenTotalFeeAmount, + data + ); return 0; } } diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index f50f9f3532..a66e6da30c 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -73,6 +73,15 @@ contract L1ERC20GatewayTest is Test { 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(address(token), user, user, depositAmount, callHookData) + ); + vm.expectEmit(true, true, true, true); emit DepositInitiated(address(token), user, user, 0, depositAmount); @@ -111,4 +120,5 @@ contract L1ERC20GatewayTest is Test { ); event TicketData(uint256 maxSubmissionCost); event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); + event InboxRetryableTicket(address from, address to, uint256 value, uint256 maxGas, bytes data); } diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index e53a3efd36..485be62687 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -64,8 +64,8 @@ contract L1OrbitERC20GatewayTest is Test { bytes memory callHookData = ""; bytes memory userEncodedData = abi.encode( maxSubmissionCost, - nativeTokenTotalFee, - callHookData + callHookData, + nativeTokenTotalFee ); bytes memory routerEncodedData = abi.encode(user, userEncodedData); @@ -80,6 +80,17 @@ contract L1OrbitERC20GatewayTest is Test { vm.expectEmit(true, true, true, true); emit RefundAddresses(user, user); + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + gasPrice, + nativeTokenTotalFee, + l1Gateway.getOutboundCalldata(address(token), user, user, 300, "") + ); + vm.expectEmit(true, true, true, true); emit DepositInitiated(address(token), user, user, 0, depositAmount); @@ -118,4 +129,13 @@ contract L1OrbitERC20GatewayTest is Test { ); event TicketData(uint256 maxSubmissionCost); event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); + event ERC20InboxRetryableTicket( + address from, + address to, + uint256 l2CallValue, + uint256 maxGas, + uint256 gasPrice, + uint256 tokenTotalFeeAmount, + bytes data + ); } From 8182569c15e25bbd34b69e8654852a1435efbaf5 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 13 Apr 2023 13:28:37 +0200 Subject: [PATCH 028/163] Test calculateL2TokenAddress --- test-foundry/L1ERC20Gateway.t.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 684d2e1c47..ff5f86ee34 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -326,6 +326,18 @@ contract L1ERC20GatewayTest is Test { assertEq(encodedWithdrawal, expectedEncoding, "Invalid encodeWithdrawal"); } + function test_calculateL2TokenAddress(address tokenAddress) public { + address l2TokenAddress = l1Gateway.calculateL2TokenAddress(tokenAddress); + + address expectedL2TokenAddress = Create2.computeAddress( + keccak256(abi.encode(l2Gateway, keccak256(abi.encode(tokenAddress)))), + cloneableProxyHash, + l2BeaconProxyFactory + ); + + assertEq(l2TokenAddress, expectedL2TokenAddress, "Invalid calculateL2TokenAddress"); + } + //// // Helper functions //// From e8df96841ce8013bd528f43bb8f03009c1450f00 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 13 Apr 2023 14:02:46 +0200 Subject: [PATCH 029/163] Test postUpgradeInit reverts --- test-foundry/L1ERC20Gateway.t.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index ff5f86ee34..5ce9550b7e 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -338,6 +338,11 @@ contract L1ERC20GatewayTest is Test { assertEq(l2TokenAddress, expectedL2TokenAddress, "Invalid calculateL2TokenAddress"); } + function test_postUpgradeInit_revert_NotFromAdmin() public { + vm.expectRevert("NOT_FROM_ADMIN"); + L1ERC20Gateway(address(l1Gateway)).postUpgradeInit(); + } + //// // Helper functions //// From 0c5b7976c99821134077f6d034c366ff851c4fff Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 13 Apr 2023 14:28:23 +0200 Subject: [PATCH 030/163] Test finalizeInboundTransfer revert if invalid sender --- test-foundry/L1ERC20Gateway.t.sol | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 5ce9550b7e..5333cbbfdc 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -280,6 +280,23 @@ contract L1ERC20GatewayTest is Test { ); } + function test_finalizeInboundTransfer_revert_NotFromBridge() public { + address notBridge = address(300); + vm.prank(notBridge); + vm.expectRevert("NOT_FROM_BRIDGE"); + l1Gateway.finalizeInboundTransfer(address(token), user, user, 100, ""); + } + + function test_finalizeInboundTransfer_revert_OnlyCounterpartGateway() public { + address notCounterPartGateway = address(400); + InboxMock(address(inbox)).setL2ToL1Sender(notCounterPartGateway); + + // trigger withdrawal + vm.prank(address(IInbox(l1Gateway.inbox()).bridge())); + vm.expectRevert("ONLY_COUNTERPART_GATEWAY"); + l1Gateway.finalizeInboundTransfer(address(token), user, user, 100, ""); + } + function test_getOutboundCalldata() public { bytes memory outboundCalldata = l1Gateway.getOutboundCalldata({ _token: address(token), From 9e155f155c0ec89c9d3c5b80a28fe22d206fde4b Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 13 Apr 2023 14:41:51 +0200 Subject: [PATCH 031/163] Add missing event checks --- test-foundry/L1ERC20Gateway.t.sol | 9 +++++++++ test-foundry/L1OrbitERC20Gateway.t.sol | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 5333cbbfdc..2d7aa56fd3 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -157,6 +157,15 @@ contract L1ERC20GatewayTest is Test { vm.expectEmit(true, true, true, true); emit RefundAddresses(refundTo, user); + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + l1Gateway.getOutboundCalldata(address(token), user, user, depositAmount, callHookData) + ); + vm.expectEmit(true, true, true, true); emit DepositInitiated(address(token), user, user, 0, depositAmount); diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 9a135f0645..358b007dd9 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -144,6 +144,17 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { vm.expectEmit(true, true, true, true); emit RefundAddresses(refundTo, user); + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + gasPrice, + nativeTokenTotalFee, + l1Gateway.getOutboundCalldata(address(token), user, user, 700, "") + ); + vm.expectEmit(true, true, true, true); emit DepositInitiated(address(token), user, user, 0, depositAmount); From a337acf58a5967d6fae9a8b5c61a93f98ea75113 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 13 Apr 2023 16:18:01 +0200 Subject: [PATCH 032/163] Test functions in extended gateway --- test-foundry/L1ArbitrumExtendedGateway.t.sol | 37 ++++++++++++++++++++ test-foundry/L1ERC20Gateway.t.sol | 15 ++------ 2 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 test-foundry/L1ArbitrumExtendedGateway.t.sol diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol new file mode 100644 index 0000000000..1b7c72fa72 --- /dev/null +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity 0.6.11; +pragma experimental ABIEncoderV2; + +import "forge-std/Test.sol"; +import "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol"; + +abstract contract L1ArbitrumExtendedGatewayTest is Test { + IL1ArbitrumGateway public l1Gateway; + + function test_encodeWithdrawal(uint256 exitNum, address dest) public { + bytes32 encodedWithdrawal = L1ArbitrumExtendedGateway(address(l1Gateway)).encodeWithdrawal( + exitNum, + dest + ); + bytes32 expectedEncoding = keccak256(abi.encode(exitNum, dest)); + + assertEq(encodedWithdrawal, expectedEncoding, "Invalid encodeWithdrawal"); + } + + function test_getExternalCall(uint256 exitNum, address dest, bytes memory data) public { + (address target, bytes memory extData) = L1ArbitrumExtendedGateway(address(l1Gateway)) + .getExternalCall(exitNum, dest, data); + + assertEq(target, dest, "Invalid dest"); + assertEq(extData, data, "Invalid data"); + + bytes32 exitId = keccak256(abi.encode(exitNum, dest)); + (bool isExit, address newTo, bytes memory newData) = L1ArbitrumExtendedGateway( + address(l1Gateway) + ).redirectedExits(exitId); + assertEq(isExit, false, "Invalid isExit"); + assertEq(newTo, address(0), "Invalid _newTo"); + assertEq(newData.length, 0, "Invalid _newData"); + } +} diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 2d7aa56fd3..cf8ac12d13 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -3,14 +3,13 @@ pragma solidity 0.6.11; pragma experimental ABIEncoderV2; -import "forge-std/Test.sol"; +import { L1ArbitrumExtendedGatewayTest } from "./L1ArbitrumExtendedGateway.t.sol"; import "contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol"; import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -contract L1ERC20GatewayTest is Test { - IL1ArbitrumGateway public l1Gateway; +contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { IERC20 public token; // gateway params @@ -342,16 +341,6 @@ contract L1ERC20GatewayTest is Test { assertEq(l1Gateway.supportsInterface(iface), expected, "Interface shouldn't be supported"); } - function test_encodeWithdrawal(uint256 exitNum, address dest) public { - bytes32 encodedWithdrawal = L1ERC20Gateway(address(l1Gateway)).encodeWithdrawal( - exitNum, - dest - ); - bytes32 expectedEncoding = keccak256(abi.encode(exitNum, dest)); - - assertEq(encodedWithdrawal, expectedEncoding, "Invalid encodeWithdrawal"); - } - function test_calculateL2TokenAddress(address tokenAddress) public { address l2TokenAddress = l1Gateway.calculateL2TokenAddress(tokenAddress); From 5b0d2d56ec236fbd89655dbf45970498333e2485 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 14 Apr 2023 09:41:06 +0200 Subject: [PATCH 033/163] Add test cases for transferExitAndCall --- test-foundry/L1ArbitrumExtendedGateway.t.sol | 84 ++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol index 1b7c72fa72..0bec0e5574 100644 --- a/test-foundry/L1ArbitrumExtendedGateway.t.sol +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -34,4 +34,88 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { assertEq(newTo, address(0), "Invalid _newTo"); assertEq(newData.length, 0, "Invalid _newData"); } + + function test_transferExitAndCall_EmptyData( + uint256 exitNum, + address initialDestination, + address newDestination + ) public { + bytes memory newData; + bytes memory data; + + // check event + vm.expectEmit(true, true, true, true); + emit WithdrawRedirected(initialDestination, newDestination, exitNum, newData, data, false); + + // do it + vm.prank(initialDestination); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDestination, + newDestination, + newData, + data + ); + + // check exit data is properly updated + bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination)); + (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway( + address(l1Gateway) + ).redirectedExits(exitId); + assertEq(isExit, true, "Invalid isExit"); + assertEq(exitTo, newDestination, "Invalid exitTo"); + assertEq(exitData.length, 0, "Invalid exitData"); + } + + function test_transferExitAndCall_revert_NotExpectedSender() public { + address nonSender = address(800); + vm.expectRevert("NOT_EXPECTED_SENDER"); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + 4, + nonSender, + address(2), + "", + "" + ); + } + + function test_transferExitAndCall_revert_NoDataAllowed() public { + bytes memory nonEmptyData = bytes("abc"); + vm.prank(address(1)); + vm.expectRevert("NO_DATA_ALLOWED"); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + 4, + address(1), + address(2), + nonEmptyData, + "" + ); + } + + function test_transferExitAndCall_revert_ToNotContract(address initialDestination) public { + bytes memory data = abi.encode("execute()"); + address nonContractNewDestination = address(15); + + vm.prank(initialDestination); + vm.expectRevert("TO_NOT_CONTRACT"); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + 4, + initialDestination, + nonContractNewDestination, + "", + data + ); + } + + ///// + /// Event declarations + ///// + event WithdrawRedirected( + address indexed from, + address indexed to, + uint256 indexed exitNum, + bytes newData, + bytes data, + bool madeExternalCall + ); } From 3a8482f72a2c039df9b5a81eb5c2a20ae625be11 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 14 Apr 2023 11:12:12 +0200 Subject: [PATCH 034/163] Add more transferExitAndCall tests --- test-foundry/L1ArbitrumExtendedGateway.t.sol | 67 ++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol index 0bec0e5574..fe1ec23f51 100644 --- a/test-foundry/L1ArbitrumExtendedGateway.t.sol +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -67,6 +67,41 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { assertEq(exitData.length, 0, "Invalid exitData"); } + function test_transferExitAndCall_ExecuteCall( + uint256 exitNum, + address initialDestination + ) public { + bytes memory newData; + bytes memory data = abi.encode("fun()"); + address newDestination = address(new TestExitReceiver()); + + // check events + vm.expectEmit(true, true, true, true); + emit ExitHookTriggered(initialDestination, exitNum, data); + + vm.expectEmit(true, true, true, true); + emit WithdrawRedirected(initialDestination, newDestination, exitNum, newData, data, true); + + // do it + vm.prank(initialDestination); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDestination, + newDestination, + newData, + data + ); + + // check exit data is properly updated + bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination)); + (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway( + address(l1Gateway) + ).redirectedExits(exitId); + assertEq(isExit, true, "Invalid isExit"); + assertEq(exitTo, newDestination, "Invalid exitTo"); + assertEq(exitData.length, 0, "Invalid exitData"); + } + function test_transferExitAndCall_revert_NotExpectedSender() public { address nonSender = address(800); vm.expectRevert("NOT_EXPECTED_SENDER"); @@ -107,6 +142,24 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { ); } + function test_transferExitAndCall_revert_TransferHookFail( + uint256 exitNum, + address initialDestination + ) public { + bytes memory data = abi.encode("failIt"); + address newDestination = address(new TestExitReceiver()); + + vm.prank(initialDestination); + vm.expectRevert("TRANSFER_HOOK_FAIL"); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDestination, + newDestination, + "", + data + ); + } + ///// /// Event declarations ///// @@ -118,4 +171,18 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { bytes data, bool madeExternalCall ); + event ExitHookTriggered(address sender, uint256 exitNum, bytes data); +} + +contract TestExitReceiver is ITradeableExitReceiver { + event ExitHookTriggered(address sender, uint256 exitNum, bytes data); + + function onExitTransfer( + address sender, + uint256 exitNum, + bytes calldata data + ) external override returns (bool) { + emit ExitHookTriggered(sender, exitNum, data); + return keccak256(data) != keccak256(abi.encode("failIt")); + } } From 552cbf1c49ff6255bd4cbc2e7188172b612a9880 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 14 Apr 2023 13:01:38 +0200 Subject: [PATCH 035/163] Cover more branches --- test-foundry/L1ArbitrumExtendedGateway.t.sol | 140 ++++++++++++++++++- 1 file changed, 138 insertions(+), 2 deletions(-) diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol index fe1ec23f51..e83dfff9df 100644 --- a/test-foundry/L1ArbitrumExtendedGateway.t.sol +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -35,7 +35,39 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { assertEq(newData.length, 0, "Invalid _newData"); } - function test_transferExitAndCall_EmptyData( + function test_getExternalCall_Redirected( + uint256 exitNum, + address initialDest, + address newDest, + bytes memory data + ) public { + // redirect + vm.prank(initialDest); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDest, + newDest, + "", + "" + ); + + // check getExternalCall returns new destination + (address target, bytes memory extData) = L1ArbitrumExtendedGateway(address(l1Gateway)) + .getExternalCall(exitNum, initialDest, ""); + assertEq(target, newDest, "Invalid dest"); + assertEq(extData.length, 0, "Invalid data"); + + // check exit redirection is properly stored + bytes32 exitId = keccak256(abi.encode(exitNum, initialDest)); + (bool isExit, address newTo, bytes memory newData) = L1ArbitrumExtendedGateway( + address(l1Gateway) + ).redirectedExits(exitId); + assertEq(isExit, true, "Invalid isExit"); + assertEq(newTo, newDest, "Invalid _newTo"); + assertEq(newData.length, 0, "Invalid _newData"); + } + + function test_transferExitAndCall_EmptyData_NotRedirected( uint256 exitNum, address initialDestination, address newDestination @@ -67,7 +99,44 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { assertEq(exitData.length, 0, "Invalid exitData"); } - function test_transferExitAndCall_ExecuteCall( + function test_transferExitAndCall_EmptyData_Redirected( + uint256 exitNum, + address initialDestination + ) public { + bytes memory data; + address intermediateDestination = address(new TestExitReceiver()); + + // transfer exit + vm.prank(initialDestination); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDestination, + intermediateDestination, + "", + data + ); + + address finalDestination = address(new TestExitReceiver()); + vm.prank(intermediateDestination); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDestination, + finalDestination, + "", + data + ); + + // check exit data is properly updated + bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination)); + (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway( + address(l1Gateway) + ).redirectedExits(exitId); + assertEq(isExit, true, "Invalid isExit"); + assertEq(exitTo, finalDestination, "Invalid exitTo"); + assertEq(exitData.length, 0, "Invalid exitData"); + } + + function test_transferExitAndCall_NonEmptyData( uint256 exitNum, address initialDestination ) public { @@ -102,6 +171,43 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { assertEq(exitData.length, 0, "Invalid exitData"); } + function test_transferExitAndCall_NonEmptyData_Redirected( + uint256 exitNum, + address initialDestination + ) public { + bytes memory data = abi.encode("run()"); + address intermediateDestination = address(new TestExitReceiver()); + + // transfer exit + vm.prank(initialDestination); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDestination, + intermediateDestination, + "", + data + ); + + address finalDestination = address(new TestExitReceiver()); + vm.prank(intermediateDestination); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDestination, + finalDestination, + "", + data + ); + + // check exit data is properly updated + bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination)); + (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway( + address(l1Gateway) + ).redirectedExits(exitId); + assertEq(isExit, true, "Invalid isExit"); + assertEq(exitTo, finalDestination, "Invalid exitTo"); + assertEq(exitData.length, 0, "Invalid exitData"); + } + function test_transferExitAndCall_revert_NotExpectedSender() public { address nonSender = address(800); vm.expectRevert("NOT_EXPECTED_SENDER"); @@ -160,6 +266,36 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { ); } + function test_transferExitAndCall_revert_TransferHookFail_Redirected( + uint256 exitNum, + address initialDestination + ) public { + bytes memory data = abi.encode("abc"); + address intermediateDestination = address(new TestExitReceiver()); + + vm.prank(initialDestination); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDestination, + intermediateDestination, + "", + data + ); + + bytes memory failData = abi.encode("failIt"); + address finalDestination = address(new TestExitReceiver()); + + vm.prank(intermediateDestination); + vm.expectRevert("TRANSFER_HOOK_FAIL"); + L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall( + exitNum, + initialDestination, + finalDestination, + "", + failData + ); + } + ///// /// Event declarations ///// From fab2260f91695e19c324a33c986a6475bdb15990 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 17 Apr 2023 16:10:23 +0200 Subject: [PATCH 036/163] Add test cases for router init --- test-foundry/GatewayRouter.t.sol | 8 +++++ test-foundry/L1GatewayRouter.t.sol | 47 ++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 test-foundry/GatewayRouter.t.sol create mode 100644 test-foundry/L1GatewayRouter.t.sol diff --git a/test-foundry/GatewayRouter.t.sol b/test-foundry/GatewayRouter.t.sol new file mode 100644 index 0000000000..675e95992f --- /dev/null +++ b/test-foundry/GatewayRouter.t.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity 0.6.11; +pragma experimental ABIEncoderV2; + +import "forge-std/Test.sol"; + +abstract contract GatewayRouterTest is Test {} diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol new file mode 100644 index 0000000000..c2c1952089 --- /dev/null +++ b/test-foundry/L1GatewayRouter.t.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity 0.6.11; +pragma experimental ABIEncoderV2; + +import { GatewayRouterTest } from "./GatewayRouter.t.sol"; +import { L1GatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol"; + +contract L1GatewayRouterTest is GatewayRouterTest { + L1GatewayRouter l1Router; + + address owner = makeAddr("owner"); + address defaultGateway = makeAddr("defaultGateway"); + address counterpartGateway = makeAddr("counterpartGateway"); + address inbox = makeAddr("inbox"); + + function setUp() public { + l1Router = new L1GatewayRouter(); + } + + function test_initialize() public { + L1GatewayRouter router = new L1GatewayRouter(); + + router.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); + + assertEq(router.router(), address(0), "Invalid router"); + assertEq(router.counterpartGateway(), counterpartGateway, "Invalid counterpartGateway"); + assertEq(router.defaultGateway(), defaultGateway, "Invalid defaultGateway"); + assertEq(router.owner(), owner, "Invalid owner"); + assertEq(router.whitelist(), address(0), "Invalid whitelist"); + assertEq(router.inbox(), inbox, "Invalid inbox"); + } + + function test_initialize_revert_AlreadyInit() public { + L1GatewayRouter router = new L1GatewayRouter(); + router.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); + vm.expectRevert("ALREADY_INIT"); + router.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); + } + + function test_initialize_revert_InvalidCounterPart() public { + L1GatewayRouter router = new L1GatewayRouter(); + address invalidCounterpart = address(0); + vm.expectRevert("INVALID_COUNTERPART"); + router.initialize(owner, defaultGateway, address(0), invalidCounterpart, inbox); + } +} From 20db9569754104ebac10d2b88f201b5d943fa9cc Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 21 Apr 2023 11:38:56 +0200 Subject: [PATCH 037/163] Test setting the default gateway --- test-foundry/L1GatewayRouter.t.sol | 91 ++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index c2c1952089..a82badcead 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -5,19 +5,28 @@ pragma experimental ABIEncoderV2; import { GatewayRouterTest } from "./GatewayRouter.t.sol"; import { L1GatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol"; +import { L2GatewayRouter } from "contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol"; +import { L1ERC20Gateway } from "contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol"; +import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; contract L1GatewayRouterTest is GatewayRouterTest { L1GatewayRouter l1Router; - address owner = makeAddr("owner"); - address defaultGateway = makeAddr("defaultGateway"); - address counterpartGateway = makeAddr("counterpartGateway"); - address inbox = makeAddr("inbox"); + address public owner = makeAddr("owner"); + address public defaultGateway = makeAddr("defaultGateway"); + address public counterpartGateway = makeAddr("counterpartGateway"); + address public inbox; function setUp() public { + inbox = address(new InboxMock()); + l1Router = new L1GatewayRouter(); + l1Router.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); + + vm.deal(owner, 100 ether); } + /* solhint-disable func-name-mixedcase */ function test_initialize() public { L1GatewayRouter router = new L1GatewayRouter(); @@ -44,4 +53,78 @@ contract L1GatewayRouterTest is GatewayRouterTest { vm.expectRevert("INVALID_COUNTERPART"); router.initialize(owner, defaultGateway, address(0), invalidCounterpart, inbox); } + + function test_postUpgradeInit_revert_NotFromAdmin() public { + vm.expectRevert("NOT_FROM_ADMIN"); + l1Router.postUpgradeInit(); + } + + function test_setDefaultGateway() public { + L1ERC20Gateway newL1DefaultGateway = new L1ERC20Gateway(); + address newDefaultGatewayCounterpart = makeAddr("newDefaultGatewayCounterpart"); + newL1DefaultGateway.initialize( + newDefaultGatewayCounterpart, + address(l1Router), + inbox, + 0x0000000000000000000000000000000000000000000000000000000000000001, + makeAddr("l2BeaconProxyFactory") + ); + + // retryable params + uint256 maxSubmissionCost = 50000; + uint256 maxGas = 1000000000; + uint256 gasPriceBid = 3; + uint256 retryableCost = maxSubmissionCost + maxGas * gasPriceBid; + + // event checkers + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Router), + counterpartGateway, + 0, + maxGas, + abi.encodeWithSelector( + L2GatewayRouter.setDefaultGateway.selector, + newDefaultGatewayCounterpart + ) + ); + + // set it + vm.prank(owner); + uint256 seqNum = l1Router.setDefaultGateway{ value: retryableCost }( + address(newL1DefaultGateway), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + + /// checks + assertEq( + l1Router.defaultGateway(), + address(newL1DefaultGateway), + "Invalid newL1DefaultGateway" + ); + + assertEq(seqNum, 0, "Invalid seqNum"); + } + + //// + // Event declarations + //// + event DepositInitiated( + address l1Token, + address indexed _from, + address indexed _to, + uint256 indexed _sequenceNumber, + uint256 _amount + ); + event TicketData(uint256 maxSubmissionCost); + event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); + event InboxRetryableTicket(address from, address to, uint256 value, uint256 maxGas, bytes data); } From 423684aee2fe520ee7e33cd751f485ff95b4fe04 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 24 Apr 2023 14:43:29 +0200 Subject: [PATCH 038/163] Switch to SOlidity 0.8 --- .solhint.json | 2 +- contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol | 2 +- test-foundry/L1ERC20Gateway.t.sol | 3 +-- test-foundry/L1OrbitERC20Gateway.t.sol | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.solhint.json b/.solhint.json index b1167a3c90..f6b6734c51 100644 --- a/.solhint.json +++ b/.solhint.json @@ -4,6 +4,6 @@ "rules": { "mark-callable-contracts": "none", "prettier/prettier": "error", - "compiler-version": ["error", "^0.6.11"] + "compiler-version": ["error", "^0.8.17"] } } diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index 5b0cd65d67..7a8ff0fd06 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.6.11; +pragma solidity ^0.8.0; import "./L1ERC20Gateway.sol"; import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index a66e6da30c..28490924de 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.6.11; -pragma experimental ABIEncoderV2; +pragma solidity ^0.8.0; import "forge-std/Test.sol"; import "contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol"; diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 485be62687..2a8b368c1e 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.6.11; -pragma experimental ABIEncoderV2; +pragma solidity ^0.8.0; import "forge-std/Test.sol"; import "contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol"; From a86a49326a2f7d34cf6cf74b2c7a7f7c14d21ee4 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 24 Apr 2023 15:04:01 +0200 Subject: [PATCH 039/163] Adjust expected revert msg --- test-foundry/L1ERC20Gateway.t.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 05f0abdb1a..6ca2fbde8a 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -238,11 +238,11 @@ contract L1ERC20GatewayTest is Test { ); } - function test_outboundTransferCustomRefund_revert_AmountExceedsAllowance() public { + function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public { uint256 tooManyTokens = 500 ether; vm.prank(router); - vm.expectRevert("ERC20: transfer amount exceeds balance"); + vm.expectRevert("ERC20: insufficient allowance"); l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( address(token), user, From 02f5485eeccbec28ebce7abfe8761887c9190bb8 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 24 Apr 2023 15:07:19 +0200 Subject: [PATCH 040/163] Update to 0.8 --- test-foundry/L1ArbitrumExtendedGateway.t.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol index e83dfff9df..3007fb6377 100644 --- a/test-foundry/L1ArbitrumExtendedGateway.t.sol +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.6.11; -pragma experimental ABIEncoderV2; +pragma solidity ^0.8.0; import "forge-std/Test.sol"; import "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol"; From f3d259d74c40bd39846452baf945c3aaf5ef02a6 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 24 Apr 2023 15:10:06 +0200 Subject: [PATCH 041/163] Switch to solidity 0.8 --- test-foundry/GatewayRouter.t.sol | 3 +-- test-foundry/L1GatewayRouter.t.sol | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/test-foundry/GatewayRouter.t.sol b/test-foundry/GatewayRouter.t.sol index 675e95992f..724ed774d3 100644 --- a/test-foundry/GatewayRouter.t.sol +++ b/test-foundry/GatewayRouter.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.6.11; -pragma experimental ABIEncoderV2; +pragma solidity ^0.8.0; import "forge-std/Test.sol"; diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index a82badcead..535f530029 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.6.11; -pragma experimental ABIEncoderV2; +pragma solidity ^0.8.0; import { GatewayRouterTest } from "./GatewayRouter.t.sol"; import { L1GatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol"; From e2e5ddbc1a84d58f1d1309bcde2768b6db372991 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 24 Apr 2023 16:17:04 +0200 Subject: [PATCH 042/163] Test setOwner --- test-foundry/L1GatewayRouter.t.sol | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 535f530029..7db63c1786 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -113,6 +113,31 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } + function test_setOwner(address newOwner) public { + vm.assume(newOwner != address(0)); + + vm.prank(owner); + l1Router.setOwner(newOwner); + + assertEq(l1Router.owner(), newOwner, "Invalid owner"); + } + + function test_setOwner_revert_InvalidOwner() public { + address invalidOwner = address(0); + + vm.prank(owner); + vm.expectRevert("INVALID_OWNER"); + l1Router.setOwner(invalidOwner); + } + + function test_setOwner_revert_OnlyOwner() public { + address nonOwner = address(250); + + vm.prank(nonOwner); + vm.expectRevert("ONLY_OWNER"); + l1Router.setOwner(address(300)); + } + //// // Event declarations //// From 1e6542d5c7881fc9e7c6893e5ec4da9d58976df4 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 26 Apr 2023 13:32:19 +0200 Subject: [PATCH 043/163] Add test for setGateway --- test-foundry/L1GatewayRouter.t.sol | 85 +++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 7db63c1786..556d88967b 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -6,10 +6,12 @@ import { GatewayRouterTest } from "./GatewayRouter.t.sol"; import { L1GatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol"; import { L2GatewayRouter } from "contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol"; import { L1ERC20Gateway } from "contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol"; +import { L1CustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol"; import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract L1GatewayRouterTest is GatewayRouterTest { - L1GatewayRouter l1Router; + L1GatewayRouter public l1Router; address public owner = makeAddr("owner"); address public defaultGateway = makeAddr("defaultGateway"); @@ -76,6 +78,9 @@ contract L1GatewayRouterTest is GatewayRouterTest { uint256 retryableCost = maxSubmissionCost + maxGas * gasPriceBid; // event checkers + vm.expectEmit(true, true, true, true); + emit DefaultGatewayUpdated(address(newL1DefaultGateway)); + vm.expectEmit(true, true, true, true); emit TicketData(maxSubmissionCost); @@ -113,6 +118,81 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } + function test_setGateway() public { + // create gateway + L1CustomGateway customGateway = new L1CustomGateway(); + address l2Counterpart = makeAddr("l2Counterpart"); + customGateway.initialize(l2Counterpart, address(l1Router), address(inbox), owner); + + // create token + ERC20 customToken = new ERC20("X", "Y"); + vm.deal(address(customToken), 100 ether); + vm.mockCall( + address(customToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + + // register token to gateway + vm.prank(address(customToken)); + customGateway.registerTokenToL2{ value: 4000040000 }( + makeAddr("tokenL2Address"), + 1000000000, + 3, + 40000, + makeAddr("creditBackAddress") + ); + + // set gateway params + uint256 maxSubmissionCost = 40000; + uint256 maxGas = 1000000000; + uint256 gasPrice = 3; + uint256 value = maxSubmissionCost + maxGas * gasPrice; + address creditBackAddress = makeAddr("creditBackAddress"); + + // expect events + emit GatewaySet(address(customToken), address(customGateway)); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(creditBackAddress, creditBackAddress); + + vm.expectEmit(true, true, true, true); + address[] memory _tokenArr = new address[](1); + _tokenArr[0] = address(customToken); + address[] memory _gatewayArr = new address[](1); + _gatewayArr[0] = l2Counterpart; + emit InboxRetryableTicket( + address(l1Router), + counterpartGateway, + 0, + maxGas, + abi.encodeWithSelector(L2GatewayRouter.setGateway.selector, _tokenArr, _gatewayArr) + ); + + // set gateway + vm.prank(address(customToken)); + uint256 seqNum = l1Router.setGateway{ value: value }( + address(customGateway), + maxGas, + gasPrice, + maxSubmissionCost, + creditBackAddress + ); + + ///// checks + + assertEq( + l1Router.l1TokenToGateway(address(customToken)), + address(customGateway), + "Gateway not set" + ); + + assertEq(seqNum, 0, "Invalid seqNum"); + } + function test_setOwner(address newOwner) public { vm.assume(newOwner != address(0)); @@ -141,6 +221,9 @@ contract L1GatewayRouterTest is GatewayRouterTest { //// // Event declarations //// + event GatewaySet(address indexed l1Token, address indexed gateway); + event DefaultGatewayUpdated(address newDefaultGateway); + event DepositInitiated( address l1Token, address indexed _from, From c24e7f78ac4a0a3c1aa305dbf423ec6a5a51b274 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 26 Apr 2023 15:02:00 +0200 Subject: [PATCH 044/163] Add revert test cases for setGateway --- test-foundry/L1GatewayRouter.t.sol | 120 +++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 556d88967b..0222cc5299 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -193,6 +193,126 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } + function test_setGateway_revert_NotArbEnabled() public { + address nonArbEnabledToken = address(new ERC20("X", "Y")); + vm.deal(nonArbEnabledToken, 100 ether); + vm.mockCall( + nonArbEnabledToken, + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb2)) + ); + + vm.prank(nonArbEnabledToken); + vm.expectRevert("NOT_ARB_ENABLED"); + l1Router.setGateway{ value: 400000 }( + makeAddr("gateway"), + 100000, + 3, + 200, + makeAddr("creditback") + ); + } + + function test_setGateway_revert_NotToContract() public { + address token = address(new ERC20("X", "Y")); + vm.deal(token, 100 ether); + vm.mockCall(token, abi.encodeWithSignature("isArbitrumEnabled()"), abi.encode(uint8(0xb1))); + + address gatewayNotContract = makeAddr("not contract"); + + vm.prank(token); + vm.expectRevert("NOT_TO_CONTRACT"); + l1Router.setGateway{ value: 400000 }( + gatewayNotContract, + 100000, + 3, + 200, + makeAddr("creditback") + ); + } + + function test_setGateway_NoUpdateToDifferentAddress() public { + // create gateway + address initialGateway = address(new L1CustomGateway()); + address l2Counterpart = makeAddr("l2Counterpart"); + L1CustomGateway(initialGateway).initialize( + l2Counterpart, + address(l1Router), + address(inbox), + owner + ); + + // create token + address token = address(new ERC20("X", "Y")); + vm.deal(address(token), 100 ether); + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + + // retryable params + uint256 maxSubmissionCost = 40000; + uint256 maxGas = 1000000000; + uint256 gasPrice = 3; + uint256 value = maxSubmissionCost + maxGas * gasPrice; + address creditBackAddress = makeAddr("creditBackAddress"); + + // register token to gateway + vm.prank(token); + L1CustomGateway(initialGateway).registerTokenToL2{ value: value }( + makeAddr("tokenL2Address"), + maxGas, + gasPrice, + maxSubmissionCost, + creditBackAddress + ); + + // initially set gateway for token + vm.prank(address(token)); + l1Router.setGateway{ value: value }( + initialGateway, + maxGas, + gasPrice, + maxSubmissionCost, + creditBackAddress + ); + assertEq(l1Router.l1TokenToGateway(token), initialGateway, "Initial gateway not set"); + + //// now try setting different gateway + address newGateway = address(new L1CustomGateway()); + + vm.prank(token); + vm.expectRevert("NO_UPDATE_TO_DIFFERENT_ADDR"); + l1Router.setGateway{ value: value }( + newGateway, + maxGas, + gasPrice, + maxSubmissionCost, + creditBackAddress + ); + } + + function test_setGateway_revert_TokenNotHandledByGateway() public { + // create gateway + L1CustomGateway gateway = new L1CustomGateway(); + + // create token + address token = address(new ERC20("X", "Y")); + vm.deal(token, 100 ether); + vm.mockCall(token, abi.encodeWithSignature("isArbitrumEnabled()"), abi.encode(uint8(0xb1))); + + vm.prank(token); + vm.expectRevert("TOKEN_NOT_HANDLED_BY_GATEWAY"); + l1Router.setGateway{ value: 400000 }( + address(gateway), + 100000, + 3, + 200, + makeAddr("creditback") + ); + } + function test_setOwner(address newOwner) public { vm.assume(newOwner != address(0)); From 82acd2491b6965e65bcfc0401fa1535a0909473f Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 26 Apr 2023 15:51:01 +0200 Subject: [PATCH 045/163] More test for setGateway --- test-foundry/L1GatewayRouter.t.sol | 251 ++++++++++++++++++++++++++++- 1 file changed, 249 insertions(+), 2 deletions(-) diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 0222cc5299..9ed9573271 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -14,7 +14,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { L1GatewayRouter public l1Router; address public owner = makeAddr("owner"); - address public defaultGateway = makeAddr("defaultGateway"); + address public defaultGateway; address public counterpartGateway = makeAddr("counterpartGateway"); address public inbox; @@ -24,6 +24,8 @@ contract L1GatewayRouterTest is GatewayRouterTest { l1Router = new L1GatewayRouter(); l1Router.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); + defaultGateway = address(new L1ERC20Gateway()); + vm.deal(owner, 100 ether); } @@ -193,6 +195,79 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } + function test_setGateway_CustomCreditback() public { + // create gateway + L1CustomGateway customGateway = new L1CustomGateway(); + address l2Counterpart = makeAddr("l2Counterpart"); + customGateway.initialize(l2Counterpart, address(l1Router), address(inbox), owner); + + // create token + ERC20 customToken = new ERC20("X", "Y"); + vm.deal(address(customToken), 100 ether); + vm.mockCall( + address(customToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + + // register token to gateway + vm.prank(address(customToken)); + customGateway.registerTokenToL2{ value: 4000040000 }( + makeAddr("tokenL2Address"), + 1000000000, + 3, + 40000, + makeAddr("creditBackAddress") + ); + + // set gateway params + uint256 maxSubmissionCost = 40000; + uint256 maxGas = 1000000000; + uint256 gasPrice = 3; + uint256 value = maxSubmissionCost + maxGas * gasPrice; + + // expect events + emit GatewaySet(address(customToken), address(customGateway)); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(address(customToken), address(customToken)); + + vm.expectEmit(true, true, true, true); + address[] memory _tokenArr = new address[](1); + _tokenArr[0] = address(customToken); + address[] memory _gatewayArr = new address[](1); + _gatewayArr[0] = l2Counterpart; + emit InboxRetryableTicket( + address(l1Router), + counterpartGateway, + 0, + maxGas, + abi.encodeWithSelector(L2GatewayRouter.setGateway.selector, _tokenArr, _gatewayArr) + ); + + // set gateway + vm.prank(address(customToken)); + uint256 seqNum = l1Router.setGateway{ value: value }( + address(customGateway), + maxGas, + gasPrice, + maxSubmissionCost + ); + + ///// checks + + assertEq( + l1Router.l1TokenToGateway(address(customToken)), + address(customGateway), + "Gateway not set" + ); + + assertEq(seqNum, 0, "Invalid seqNum"); + } + function test_setGateway_revert_NotArbEnabled() public { address nonArbEnabledToken = address(new ERC20("X", "Y")); vm.deal(nonArbEnabledToken, 100 ether); @@ -231,7 +306,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } - function test_setGateway_NoUpdateToDifferentAddress() public { + function test_setGateway_revert_NoUpdateToDifferentAddress() public { // create gateway address initialGateway = address(new L1CustomGateway()); address l2Counterpart = makeAddr("l2Counterpart"); @@ -313,6 +388,178 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } + function test_setGateways() public { + // retryables params + uint256 maxSubmissionCost = 40000; + uint256 maxGas = 1000000000; + uint256 gasPrice = 3; + uint256 value = maxSubmissionCost + maxGas * gasPrice; + + // create tokens and gateways + address[] memory tokens = new address[](2); + tokens[0] = address(new ERC20("1", "1")); + tokens[1] = address(new ERC20("2", "2")); + address[] memory gateways = new address[](2); + gateways[0] = address(new L1CustomGateway()); + gateways[1] = address(new L1CustomGateway()); + + address l2Counterpart = makeAddr("l2Counterpart"); + + /// init all + for (uint256 i = 0; i < 2; i++) { + L1CustomGateway(gateways[i]).initialize( + l2Counterpart, + address(l1Router), + address(inbox), + owner + ); + + vm.mockCall( + tokens[i], + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + + // register tokens to gateways + vm.deal(tokens[i], 100 ether); + vm.prank(tokens[i]); + L1CustomGateway(gateways[i]).registerTokenToL2{ value: 4000040000 }( + makeAddr("tokenL2Address"), + 1000000000, + 3, + 40000, + makeAddr("creditBackAddress") + ); + } + + // expect events + emit GatewaySet(tokens[0], gateways[0]); + emit GatewaySet(tokens[1], gateways[1]); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + address[] memory _gatewayArr = new address[](2); + _gatewayArr[0] = l2Counterpart; + _gatewayArr[1] = l2Counterpart; + emit InboxRetryableTicket( + address(l1Router), + counterpartGateway, + 0, + maxGas, + abi.encodeWithSelector(L2GatewayRouter.setGateway.selector, tokens, _gatewayArr) + ); + + /// set gateways + vm.prank(owner); + uint256 seqNum = l1Router.setGateways{ value: value }( + tokens, + gateways, + maxGas, + gasPrice, + maxSubmissionCost + ); + + ///// checks + + assertEq(l1Router.l1TokenToGateway(tokens[0]), gateways[0], "Gateway[0] not set"); + assertEq(l1Router.l1TokenToGateway(tokens[1]), gateways[1], "Gateway[1] not set"); + assertEq(seqNum, 0, "Invalid seqNum"); + } + + function test_setGateways_SetZeroAddr() public { + // create gateway + address initialGateway = address(new L1CustomGateway()); + address l2Counterpart = makeAddr("l2Counterpart"); + L1CustomGateway(initialGateway).initialize( + l2Counterpart, + address(l1Router), + address(inbox), + owner + ); + + // create token + address token = address(new ERC20("X", "Y")); + vm.deal(address(token), 100 ether); + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + + // retryable params + uint256 maxSubmissionCost = 40000; + uint256 maxGas = 1000000000; + uint256 gasPrice = 3; + uint256 value = maxSubmissionCost + maxGas * gasPrice; + address creditBackAddress = makeAddr("creditBackAddress"); + + // register token to gateway + vm.prank(token); + L1CustomGateway(initialGateway).registerTokenToL2{ value: value }( + makeAddr("tokenL2Address"), + maxGas, + gasPrice, + maxSubmissionCost, + creditBackAddress + ); + + // initially set gateway for token + vm.prank(address(token)); + l1Router.setGateway{ value: value }( + initialGateway, + maxGas, + gasPrice, + maxSubmissionCost, + creditBackAddress + ); + assertEq(l1Router.l1TokenToGateway(token), initialGateway, "Initial gateway not set"); + + //// now set to zero addr + address newGateway = address(0); + + // expect events + emit GatewaySet(token, newGateway); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + address[] memory _tokenArr = new address[](1); + _tokenArr[0] = token; + address[] memory _gatewayArr = new address[](1); + _gatewayArr[0] = newGateway; + emit InboxRetryableTicket( + address(l1Router), + counterpartGateway, + 0, + maxGas, + abi.encodeWithSelector(L2GatewayRouter.setGateway.selector, _tokenArr, _gatewayArr) + ); + + /// set gateways + vm.prank(owner); + uint256 seqNum = l1Router.setGateways{ value: value }( + _tokenArr, + _gatewayArr, + maxGas, + gasPrice, + maxSubmissionCost + ); + + ///// checks + + assertEq(l1Router.l1TokenToGateway(token), address(0), "Custom gateway not cleared"); + assertEq(seqNum, 0, "Invalid seqNum"); + } + function test_setOwner(address newOwner) public { vm.assume(newOwner != address(0)); From a8e2f1ff235f328dabbdafe1132a4825e6807e4e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 27 Apr 2023 16:28:05 +0200 Subject: [PATCH 046/163] Test supportsInterface --- .../MulticallV2.sol.func-sort-c.html | 189 ++ .../rpc-utils/MulticallV2.sol.func.html | 189 ++ .../rpc-utils/MulticallV2.sol.gcov.html | 333 +++ .../contracts/rpc-utils/index-sort-b.html | 107 + .../contracts/rpc-utils/index-sort-f.html | 107 + .../contracts/rpc-utils/index-sort-l.html | 107 + .../contracts/rpc-utils/index.html | 107 + ...trumExtendedGateway.t.sol.func-sort-c.html | 85 + .../L1ArbitrumExtendedGateway.t.sol.func.html | 85 + .../L1ArbitrumExtendedGateway.t.sol.gcov.html | 408 ++++ .../test-foundry/index-sort-b.html | 107 + .../test-foundry/index-sort-f.html | 107 + .../test-foundry/index-sort-l.html | 107 + .../test-foundry/index.html | 107 + coverage/amber.png | Bin 0 -> 141 bytes .../L2ArbitrumMessenger.sol.func-sort-c.html | 85 + .../L2ArbitrumMessenger.sol.func.html | 85 + .../L2ArbitrumMessenger.sol.gcov.html | 125 ++ .../ReverseArbToken.sol.func-sort-c.html | 89 + .../arbitrum/ReverseArbToken.sol.func.html | 89 + .../arbitrum/ReverseArbToken.sol.gcov.html | 125 ++ .../StandardArbERC20.sol.func-sort-c.html | 97 + .../arbitrum/StandardArbERC20.sol.func.html | 97 + .../arbitrum/StandardArbERC20.sol.gcov.html | 183 ++ .../L2ArbitrumGateway.sol.func-sort-c.html | 117 ++ .../gateway/L2ArbitrumGateway.sol.func.html | 117 ++ .../gateway/L2ArbitrumGateway.sol.gcov.html | 384 ++++ .../L2CustomGateway.sol.func-sort-c.html | 97 + .../gateway/L2CustomGateway.sol.func.html | 97 + .../gateway/L2CustomGateway.sol.gcov.html | 160 ++ .../L2ERC20Gateway.sol.func-sort-c.html | 101 + .../gateway/L2ERC20Gateway.sol.func.html | 101 + .../gateway/L2ERC20Gateway.sol.gcov.html | 186 ++ .../L2GatewayRouter.sol.func-sort-c.html | 97 + .../gateway/L2GatewayRouter.sol.func.html | 97 + .../gateway/L2GatewayRouter.sol.gcov.html | 154 ++ ...2ReverseCustomGateway.sol.func-sort-c.html | 89 + .../L2ReverseCustomGateway.sol.func.html | 89 + .../L2ReverseCustomGateway.sol.gcov.html | 146 ++ .../L2WethGateway.sol.func-sort-c.html | 101 + .../gateway/L2WethGateway.sol.func.html | 101 + .../gateway/L2WethGateway.sol.gcov.html | 192 ++ coverage/arbitrum/gateway/index-sort-b.html | 167 ++ coverage/arbitrum/gateway/index-sort-f.html | 167 ++ coverage/arbitrum/gateway/index-sort-l.html | 167 ++ coverage/arbitrum/gateway/index.html | 167 ++ coverage/arbitrum/index-sort-b.html | 131 ++ coverage/arbitrum/index-sort-f.html | 131 ++ coverage/arbitrum/index-sort-l.html | 131 ++ coverage/arbitrum/index.html | 131 ++ coverage/emerald.png | Bin 0 -> 141 bytes .../L1ArbitrumMessenger.sol.func-sort-c.html | 101 + .../L1ArbitrumMessenger.sol.func.html | 101 + .../L1ArbitrumMessenger.sol.gcov.html | 302 +++ ...bitrumExtendedGateway.sol.func-sort-c.html | 97 + .../L1ArbitrumExtendedGateway.sol.func.html | 97 + .../L1ArbitrumExtendedGateway.sol.gcov.html | 223 ++ .../L1ArbitrumGateway.sol.func-sort-c.html | 137 ++ .../gateway/L1ArbitrumGateway.sol.func.html | 137 ++ .../gateway/L1ArbitrumGateway.sol.gcov.html | 488 +++++ .../L1CustomGateway.sol.func-sort-c.html | 109 + .../gateway/L1CustomGateway.sol.func.html | 109 + .../gateway/L1CustomGateway.sol.gcov.html | 328 +++ .../L1ERC20Gateway.sol.func-sort-c.html | 109 + .../gateway/L1ERC20Gateway.sol.func.html | 109 + .../gateway/L1ERC20Gateway.sol.gcov.html | 246 +++ ...yReverseCustomGateway.sol.func-sort-c.html | 85 + ...orceOnlyReverseCustomGateway.sol.func.html | 85 + ...orceOnlyReverseCustomGateway.sol.gcov.html | 121 ++ .../L1GatewayRouter.sol.func-sort-c.html | 117 ++ .../gateway/L1GatewayRouter.sol.func.html | 117 ++ .../gateway/L1GatewayRouter.sol.gcov.html | 391 ++++ .../L1OrbitERC20Gateway.sol.func-sort-c.html | 93 + .../gateway/L1OrbitERC20Gateway.sol.func.html | 93 + .../gateway/L1OrbitERC20Gateway.sol.gcov.html | 166 ++ ...1ReverseCustomGateway.sol.func-sort-c.html | 89 + .../L1ReverseCustomGateway.sol.func.html | 89 + .../L1ReverseCustomGateway.sol.gcov.html | 140 ++ .../L1WethGateway.sol.func-sort-c.html | 105 + .../gateway/L1WethGateway.sol.func.html | 105 + .../gateway/L1WethGateway.sol.gcov.html | 210 ++ coverage/ethereum/gateway/index-sort-b.html | 203 ++ coverage/ethereum/gateway/index-sort-f.html | 203 ++ coverage/ethereum/gateway/index-sort-l.html | 203 ++ coverage/ethereum/gateway/index.html | 203 ++ coverage/ethereum/index-sort-b.html | 107 + coverage/ethereum/index-sort-f.html | 107 + coverage/ethereum/index-sort-l.html | 107 + coverage/ethereum/index.html | 107 + coverage/gcov.css | 519 +++++ coverage/glass.png | Bin 0 -> 167 bytes coverage/index-sort-b.html | 203 ++ coverage/index-sort-f.html | 203 ++ coverage/index-sort-l.html | 203 ++ coverage/index.html | 203 ++ .../AddressAliasHelper.sol.func-sort-c.html | 89 + .../AddressAliasHelper.sol.func.html | 89 + .../AddressAliasHelper.sol.gcov.html | 128 ++ .../libraries/BytesLib.sol.func-sort-c.html | 97 + coverage/libraries/BytesLib.sol.func.html | 97 + coverage/libraries/BytesLib.sol.gcov.html | 144 ++ .../BytesParser.sol.func-sort-c.html | 89 + coverage/libraries/BytesParser.sol.func.html | 89 + coverage/libraries/BytesParser.sol.gcov.html | 156 ++ .../ClonableBeaconProxy.sol.func-sort-c.html | 97 + .../ClonableBeaconProxy.sol.func.html | 97 + .../ClonableBeaconProxy.sol.gcov.html | 141 ++ .../libraries/Cloneable.sol.func-sort-c.html | 89 + coverage/libraries/Cloneable.sol.func.html | 89 + coverage/libraries/Cloneable.sol.gcov.html | 125 ++ .../libraries/ERC165.sol.func-sort-c.html | 85 + coverage/libraries/ERC165.sol.func.html | 85 + coverage/libraries/ERC165.sol.gcov.html | 117 ++ .../ERC20Upgradeable.sol.func-sort-c.html | 165 ++ .../libraries/ERC20Upgradeable.sol.func.html | 165 ++ .../libraries/ERC20Upgradeable.sol.gcov.html | 477 +++++ .../L2CustomGatewayToken.sol.func-sort-c.html | 85 + .../L2CustomGatewayToken.sol.func.html | 85 + .../L2CustomGatewayToken.sol.gcov.html | 130 ++ .../L2GatewayToken.sol.func-sort-c.html | 93 + .../libraries/L2GatewayToken.sol.func.html | 93 + .../libraries/L2GatewayToken.sol.gcov.html | 164 ++ .../libraries/ProxyUtil.sol.func-sort-c.html | 85 + coverage/libraries/ProxyUtil.sol.func.html | 85 + coverage/libraries/ProxyUtil.sol.gcov.html | 116 ++ .../TransferAndCallToken.sol.func-sort-c.html | 93 + .../TransferAndCallToken.sol.func.html | 93 + .../TransferAndCallToken.sol.gcov.html | 136 ++ .../libraries/Whitelist.sol.func-sort-c.html | 97 + coverage/libraries/Whitelist.sol.func.html | 97 + coverage/libraries/Whitelist.sol.gcov.html | 161 ++ .../libraries/aeERC20.sol.func-sort-c.html | 85 + coverage/libraries/aeERC20.sol.func.html | 85 + coverage/libraries/aeERC20.sol.gcov.html | 129 ++ .../libraries/aeWETH.sol.func-sort-c.html | 109 + coverage/libraries/aeWETH.sol.func.html | 109 + coverage/libraries/aeWETH.sol.gcov.html | 156 ++ ...RC20PermitUpgradeable.sol.func-sort-c.html | 105 + ...draft-ERC20PermitUpgradeable.sol.func.html | 105 + ...draft-ERC20PermitUpgradeable.sol.gcov.html | 199 ++ ...GatewayMessageHandler.sol.func-sort-c.html | 105 + .../GatewayMessageHandler.sol.func.html | 105 + .../GatewayMessageHandler.sol.gcov.html | 165 ++ .../GatewayRouter.sol.func-sort-c.html | 109 + .../gateway/GatewayRouter.sol.func.html | 109 + .../gateway/GatewayRouter.sol.gcov.html | 222 ++ .../gateway/TokenGateway.sol.func-sort-c.html | 89 + .../gateway/TokenGateway.sol.func.html | 89 + .../gateway/TokenGateway.sol.gcov.html | 148 ++ coverage/libraries/gateway/index-sort-b.html | 131 ++ coverage/libraries/gateway/index-sort-f.html | 131 ++ coverage/libraries/gateway/index-sort-l.html | 131 ++ coverage/libraries/gateway/index.html | 131 ++ coverage/libraries/index-sort-b.html | 275 +++ coverage/libraries/index-sort-f.html | 275 +++ coverage/libraries/index-sort-l.html | 275 +++ coverage/libraries/index.html | 275 +++ coverage/ruby.png | Bin 0 -> 141 bytes coverage/snow.png | Bin 0 -> 141 bytes .../AddressMappingTest.sol.func-sort-c.html | 85 + .../test/AddressMappingTest.sol.func.html | 85 + .../test/AddressMappingTest.sol.gcov.html | 113 ++ coverage/test/ArbSysMock.sol.func-sort-c.html | 85 + coverage/test/ArbSysMock.sol.func.html | 85 + coverage/test/ArbSysMock.sol.gcov.html | 102 + coverage/test/InboxMock.sol.func-sort-c.html | 105 + coverage/test/InboxMock.sol.func.html | 105 + coverage/test/InboxMock.sol.gcov.html | 194 ++ .../TestArbCustomToken.sol.func-sort-c.html | 105 + .../test/TestArbCustomToken.sol.func.html | 105 + .../test/TestArbCustomToken.sol.gcov.html | 164 ++ ...ArbCustomTokenBurnFee.sol.func-sort-c.html | 85 + .../TestArbCustomTokenBurnFee.sol.func.html | 85 + .../TestArbCustomTokenBurnFee.sol.gcov.html | 120 ++ .../test/TestBytesParser.sol.func-sort-c.html | 89 + coverage/test/TestBytesParser.sol.func.html | 89 + coverage/test/TestBytesParser.sol.gcov.html | 120 ++ .../TestCustomTokenL1.sol.func-sort-c.html | 125 ++ coverage/test/TestCustomTokenL1.sol.func.html | 125 ++ coverage/test/TestCustomTokenL1.sol.gcov.html | 253 +++ coverage/test/TestERC20.sol.func-sort-c.html | 101 + coverage/test/TestERC20.sol.func.html | 101 + coverage/test/TestERC20.sol.gcov.html | 160 ++ .../TestPostDepositCall.sol.func-sort-c.html | 89 + .../test/TestPostDepositCall.sol.func.html | 89 + .../test/TestPostDepositCall.sol.gcov.html | 136 ++ coverage/test/TestWETH9.sol.func-sort-c.html | 89 + coverage/test/TestWETH9.sol.func.html | 89 + coverage/test/TestWETH9.sol.gcov.html | 105 + coverage/test/index-sort-b.html | 215 ++ coverage/test/index-sort-f.html | 215 ++ coverage/test/index-sort-l.html | 215 ++ coverage/test/index.html | 215 ++ coverage/updown.png | Bin 0 -> 117 bytes lcov.info | 1786 +++++++++++++++++ test-foundry/L1GatewayRouter.t.sol | 18 + 196 files changed, 28225 insertions(+) create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func-sort-c.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.gcov.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-b.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-f.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-l.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func-sort-c.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.gcov.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-b.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-f.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-l.html create mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index.html create mode 100644 coverage/amber.png create mode 100644 coverage/arbitrum/L2ArbitrumMessenger.sol.func-sort-c.html create mode 100644 coverage/arbitrum/L2ArbitrumMessenger.sol.func.html create mode 100644 coverage/arbitrum/L2ArbitrumMessenger.sol.gcov.html create mode 100644 coverage/arbitrum/ReverseArbToken.sol.func-sort-c.html create mode 100644 coverage/arbitrum/ReverseArbToken.sol.func.html create mode 100644 coverage/arbitrum/ReverseArbToken.sol.gcov.html create mode 100644 coverage/arbitrum/StandardArbERC20.sol.func-sort-c.html create mode 100644 coverage/arbitrum/StandardArbERC20.sol.func.html create mode 100644 coverage/arbitrum/StandardArbERC20.sol.gcov.html create mode 100644 coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func-sort-c.html create mode 100644 coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func.html create mode 100644 coverage/arbitrum/gateway/L2ArbitrumGateway.sol.gcov.html create mode 100644 coverage/arbitrum/gateway/L2CustomGateway.sol.func-sort-c.html create mode 100644 coverage/arbitrum/gateway/L2CustomGateway.sol.func.html create mode 100644 coverage/arbitrum/gateway/L2CustomGateway.sol.gcov.html create mode 100644 coverage/arbitrum/gateway/L2ERC20Gateway.sol.func-sort-c.html create mode 100644 coverage/arbitrum/gateway/L2ERC20Gateway.sol.func.html create mode 100644 coverage/arbitrum/gateway/L2ERC20Gateway.sol.gcov.html create mode 100644 coverage/arbitrum/gateway/L2GatewayRouter.sol.func-sort-c.html create mode 100644 coverage/arbitrum/gateway/L2GatewayRouter.sol.func.html create mode 100644 coverage/arbitrum/gateway/L2GatewayRouter.sol.gcov.html create mode 100644 coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func-sort-c.html create mode 100644 coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func.html create mode 100644 coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.gcov.html create mode 100644 coverage/arbitrum/gateway/L2WethGateway.sol.func-sort-c.html create mode 100644 coverage/arbitrum/gateway/L2WethGateway.sol.func.html create mode 100644 coverage/arbitrum/gateway/L2WethGateway.sol.gcov.html create mode 100644 coverage/arbitrum/gateway/index-sort-b.html create mode 100644 coverage/arbitrum/gateway/index-sort-f.html create mode 100644 coverage/arbitrum/gateway/index-sort-l.html create mode 100644 coverage/arbitrum/gateway/index.html create mode 100644 coverage/arbitrum/index-sort-b.html create mode 100644 coverage/arbitrum/index-sort-f.html create mode 100644 coverage/arbitrum/index-sort-l.html create mode 100644 coverage/arbitrum/index.html create mode 100644 coverage/emerald.png create mode 100644 coverage/ethereum/L1ArbitrumMessenger.sol.func-sort-c.html create mode 100644 coverage/ethereum/L1ArbitrumMessenger.sol.func.html create mode 100644 coverage/ethereum/L1ArbitrumMessenger.sol.gcov.html create mode 100644 coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func-sort-c.html create mode 100644 coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func.html create mode 100644 coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.gcov.html create mode 100644 coverage/ethereum/gateway/L1ArbitrumGateway.sol.func-sort-c.html create mode 100644 coverage/ethereum/gateway/L1ArbitrumGateway.sol.func.html create mode 100644 coverage/ethereum/gateway/L1ArbitrumGateway.sol.gcov.html create mode 100644 coverage/ethereum/gateway/L1CustomGateway.sol.func-sort-c.html create mode 100644 coverage/ethereum/gateway/L1CustomGateway.sol.func.html create mode 100644 coverage/ethereum/gateway/L1CustomGateway.sol.gcov.html create mode 100644 coverage/ethereum/gateway/L1ERC20Gateway.sol.func-sort-c.html create mode 100644 coverage/ethereum/gateway/L1ERC20Gateway.sol.func.html create mode 100644 coverage/ethereum/gateway/L1ERC20Gateway.sol.gcov.html create mode 100644 coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func-sort-c.html create mode 100644 coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func.html create mode 100644 coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.gcov.html create mode 100644 coverage/ethereum/gateway/L1GatewayRouter.sol.func-sort-c.html create mode 100644 coverage/ethereum/gateway/L1GatewayRouter.sol.func.html create mode 100644 coverage/ethereum/gateway/L1GatewayRouter.sol.gcov.html create mode 100644 coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func-sort-c.html create mode 100644 coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func.html create mode 100644 coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.gcov.html create mode 100644 coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func-sort-c.html create mode 100644 coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func.html create mode 100644 coverage/ethereum/gateway/L1ReverseCustomGateway.sol.gcov.html create mode 100644 coverage/ethereum/gateway/L1WethGateway.sol.func-sort-c.html create mode 100644 coverage/ethereum/gateway/L1WethGateway.sol.func.html create mode 100644 coverage/ethereum/gateway/L1WethGateway.sol.gcov.html create mode 100644 coverage/ethereum/gateway/index-sort-b.html create mode 100644 coverage/ethereum/gateway/index-sort-f.html create mode 100644 coverage/ethereum/gateway/index-sort-l.html create mode 100644 coverage/ethereum/gateway/index.html create mode 100644 coverage/ethereum/index-sort-b.html create mode 100644 coverage/ethereum/index-sort-f.html create mode 100644 coverage/ethereum/index-sort-l.html create mode 100644 coverage/ethereum/index.html create mode 100644 coverage/gcov.css create mode 100644 coverage/glass.png create mode 100644 coverage/index-sort-b.html create mode 100644 coverage/index-sort-f.html create mode 100644 coverage/index-sort-l.html create mode 100644 coverage/index.html create mode 100644 coverage/libraries/AddressAliasHelper.sol.func-sort-c.html create mode 100644 coverage/libraries/AddressAliasHelper.sol.func.html create mode 100644 coverage/libraries/AddressAliasHelper.sol.gcov.html create mode 100644 coverage/libraries/BytesLib.sol.func-sort-c.html create mode 100644 coverage/libraries/BytesLib.sol.func.html create mode 100644 coverage/libraries/BytesLib.sol.gcov.html create mode 100644 coverage/libraries/BytesParser.sol.func-sort-c.html create mode 100644 coverage/libraries/BytesParser.sol.func.html create mode 100644 coverage/libraries/BytesParser.sol.gcov.html create mode 100644 coverage/libraries/ClonableBeaconProxy.sol.func-sort-c.html create mode 100644 coverage/libraries/ClonableBeaconProxy.sol.func.html create mode 100644 coverage/libraries/ClonableBeaconProxy.sol.gcov.html create mode 100644 coverage/libraries/Cloneable.sol.func-sort-c.html create mode 100644 coverage/libraries/Cloneable.sol.func.html create mode 100644 coverage/libraries/Cloneable.sol.gcov.html create mode 100644 coverage/libraries/ERC165.sol.func-sort-c.html create mode 100644 coverage/libraries/ERC165.sol.func.html create mode 100644 coverage/libraries/ERC165.sol.gcov.html create mode 100644 coverage/libraries/ERC20Upgradeable.sol.func-sort-c.html create mode 100644 coverage/libraries/ERC20Upgradeable.sol.func.html create mode 100644 coverage/libraries/ERC20Upgradeable.sol.gcov.html create mode 100644 coverage/libraries/L2CustomGatewayToken.sol.func-sort-c.html create mode 100644 coverage/libraries/L2CustomGatewayToken.sol.func.html create mode 100644 coverage/libraries/L2CustomGatewayToken.sol.gcov.html create mode 100644 coverage/libraries/L2GatewayToken.sol.func-sort-c.html create mode 100644 coverage/libraries/L2GatewayToken.sol.func.html create mode 100644 coverage/libraries/L2GatewayToken.sol.gcov.html create mode 100644 coverage/libraries/ProxyUtil.sol.func-sort-c.html create mode 100644 coverage/libraries/ProxyUtil.sol.func.html create mode 100644 coverage/libraries/ProxyUtil.sol.gcov.html create mode 100644 coverage/libraries/TransferAndCallToken.sol.func-sort-c.html create mode 100644 coverage/libraries/TransferAndCallToken.sol.func.html create mode 100644 coverage/libraries/TransferAndCallToken.sol.gcov.html create mode 100644 coverage/libraries/Whitelist.sol.func-sort-c.html create mode 100644 coverage/libraries/Whitelist.sol.func.html create mode 100644 coverage/libraries/Whitelist.sol.gcov.html create mode 100644 coverage/libraries/aeERC20.sol.func-sort-c.html create mode 100644 coverage/libraries/aeERC20.sol.func.html create mode 100644 coverage/libraries/aeERC20.sol.gcov.html create mode 100644 coverage/libraries/aeWETH.sol.func-sort-c.html create mode 100644 coverage/libraries/aeWETH.sol.func.html create mode 100644 coverage/libraries/aeWETH.sol.gcov.html create mode 100644 coverage/libraries/draft-ERC20PermitUpgradeable.sol.func-sort-c.html create mode 100644 coverage/libraries/draft-ERC20PermitUpgradeable.sol.func.html create mode 100644 coverage/libraries/draft-ERC20PermitUpgradeable.sol.gcov.html create mode 100644 coverage/libraries/gateway/GatewayMessageHandler.sol.func-sort-c.html create mode 100644 coverage/libraries/gateway/GatewayMessageHandler.sol.func.html create mode 100644 coverage/libraries/gateway/GatewayMessageHandler.sol.gcov.html create mode 100644 coverage/libraries/gateway/GatewayRouter.sol.func-sort-c.html create mode 100644 coverage/libraries/gateway/GatewayRouter.sol.func.html create mode 100644 coverage/libraries/gateway/GatewayRouter.sol.gcov.html create mode 100644 coverage/libraries/gateway/TokenGateway.sol.func-sort-c.html create mode 100644 coverage/libraries/gateway/TokenGateway.sol.func.html create mode 100644 coverage/libraries/gateway/TokenGateway.sol.gcov.html create mode 100644 coverage/libraries/gateway/index-sort-b.html create mode 100644 coverage/libraries/gateway/index-sort-f.html create mode 100644 coverage/libraries/gateway/index-sort-l.html create mode 100644 coverage/libraries/gateway/index.html create mode 100644 coverage/libraries/index-sort-b.html create mode 100644 coverage/libraries/index-sort-f.html create mode 100644 coverage/libraries/index-sort-l.html create mode 100644 coverage/libraries/index.html create mode 100644 coverage/ruby.png create mode 100644 coverage/snow.png create mode 100644 coverage/test/AddressMappingTest.sol.func-sort-c.html create mode 100644 coverage/test/AddressMappingTest.sol.func.html create mode 100644 coverage/test/AddressMappingTest.sol.gcov.html create mode 100644 coverage/test/ArbSysMock.sol.func-sort-c.html create mode 100644 coverage/test/ArbSysMock.sol.func.html create mode 100644 coverage/test/ArbSysMock.sol.gcov.html create mode 100644 coverage/test/InboxMock.sol.func-sort-c.html create mode 100644 coverage/test/InboxMock.sol.func.html create mode 100644 coverage/test/InboxMock.sol.gcov.html create mode 100644 coverage/test/TestArbCustomToken.sol.func-sort-c.html create mode 100644 coverage/test/TestArbCustomToken.sol.func.html create mode 100644 coverage/test/TestArbCustomToken.sol.gcov.html create mode 100644 coverage/test/TestArbCustomTokenBurnFee.sol.func-sort-c.html create mode 100644 coverage/test/TestArbCustomTokenBurnFee.sol.func.html create mode 100644 coverage/test/TestArbCustomTokenBurnFee.sol.gcov.html create mode 100644 coverage/test/TestBytesParser.sol.func-sort-c.html create mode 100644 coverage/test/TestBytesParser.sol.func.html create mode 100644 coverage/test/TestBytesParser.sol.gcov.html create mode 100644 coverage/test/TestCustomTokenL1.sol.func-sort-c.html create mode 100644 coverage/test/TestCustomTokenL1.sol.func.html create mode 100644 coverage/test/TestCustomTokenL1.sol.gcov.html create mode 100644 coverage/test/TestERC20.sol.func-sort-c.html create mode 100644 coverage/test/TestERC20.sol.func.html create mode 100644 coverage/test/TestERC20.sol.gcov.html create mode 100644 coverage/test/TestPostDepositCall.sol.func-sort-c.html create mode 100644 coverage/test/TestPostDepositCall.sol.func.html create mode 100644 coverage/test/TestPostDepositCall.sol.gcov.html create mode 100644 coverage/test/TestWETH9.sol.func-sort-c.html create mode 100644 coverage/test/TestWETH9.sol.func.html create mode 100644 coverage/test/TestWETH9.sol.gcov.html create mode 100644 coverage/test/index-sort-b.html create mode 100644 coverage/test/index-sort-f.html create mode 100644 coverage/test/index-sort-l.html create mode 100644 coverage/test/index.html create mode 100644 coverage/updown.png create mode 100644 lcov.info diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func-sort-c.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func-sort-c.html new file mode 100644 index 0000000000..86e58f15f2 --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func-sort-c.html @@ -0,0 +1,189 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - MulticallV2.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ArbMulticall2.aggregate0
ArbMulticall2.blockAndAggregate0
ArbMulticall2.getBlockHash0
ArbMulticall2.getBlockNumber0
ArbMulticall2.getCurrentBlockCoinbase0
ArbMulticall2.getCurrentBlockDifficulty0
ArbMulticall2.getCurrentBlockGasLimit0
ArbMulticall2.getCurrentBlockTimestamp0
ArbMulticall2.getEthBalance0
ArbMulticall2.getL1BlockNumber0
ArbMulticall2.getLastBlockHash0
ArbMulticall2.tryAggregate0
ArbMulticall2.tryAggregateGasRation0
ArbMulticall2.tryBlockAndAggregate0
Multicall2.aggregate0
Multicall2.blockAndAggregate0
Multicall2.getBlockHash0
Multicall2.getBlockNumber0
Multicall2.getCurrentBlockCoinbase0
Multicall2.getCurrentBlockDifficulty0
Multicall2.getCurrentBlockGasLimit0
Multicall2.getCurrentBlockTimestamp0
Multicall2.getEthBalance0
Multicall2.getLastBlockHash0
Multicall2.tryAggregate0
Multicall2.tryAggregateGasRation0
Multicall2.tryBlockAndAggregate0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func.html new file mode 100644 index 0000000000..cd0fd54d72 --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func.html @@ -0,0 +1,189 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - MulticallV2.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ArbMulticall2.aggregate0
ArbMulticall2.blockAndAggregate0
ArbMulticall2.getBlockHash0
ArbMulticall2.getBlockNumber0
ArbMulticall2.getCurrentBlockCoinbase0
ArbMulticall2.getCurrentBlockDifficulty0
ArbMulticall2.getCurrentBlockGasLimit0
ArbMulticall2.getCurrentBlockTimestamp0
ArbMulticall2.getEthBalance0
ArbMulticall2.getL1BlockNumber0
ArbMulticall2.getLastBlockHash0
ArbMulticall2.tryAggregate0
ArbMulticall2.tryAggregateGasRation0
ArbMulticall2.tryBlockAndAggregate0
Multicall2.aggregate0
Multicall2.blockAndAggregate0
Multicall2.getBlockHash0
Multicall2.getBlockNumber0
Multicall2.getCurrentBlockCoinbase0
Multicall2.getCurrentBlockDifficulty0
Multicall2.getCurrentBlockGasLimit0
Multicall2.getCurrentBlockTimestamp0
Multicall2.getEthBalance0
Multicall2.getLastBlockHash0
Multicall2.tryAggregate0
Multicall2.tryAggregateGasRation0
Multicall2.tryBlockAndAggregate0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.gcov.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.gcov.html new file mode 100644 index 0000000000..1503749427 --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.gcov.html @@ -0,0 +1,333 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - MulticallV2.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MIT
+       2                 :            : // solhint-disable-next-line compiler-version
+       3                 :            : pragma solidity >=0.5.0;
+       4                 :            : pragma experimental ABIEncoderV2;
+       5                 :            : 
+       6                 :            : import "@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol";
+       7                 :            : 
+       8                 :            : // implementation from https://github.com/makerdao/multicall/blob/1e1b44362640820bef92d0ccf5eeee25d9b41474/src/Multicall2.sol MIT License
+       9                 :            : 
+      10                 :            : /// @title Multicall2 - Aggregate results from multiple read-only function calls
+      11                 :            : /// @author Michael Elliot <mike@makerdao.com>
+      12                 :            : /// @author Joshua Levine <joshua@makerdao.com>
+      13                 :            : /// @author Nick Johnson <arachnid@notdot.net>
+      14                 :            : 
+      15                 :            : contract Multicall2 {
+      16                 :            :     struct Call {
+      17                 :            :         address target;
+      18                 :            :         bytes callData;
+      19                 :            :     }
+      20                 :            :     struct Result {
+      21                 :            :         bool success;
+      22                 :            :         bytes returnData;
+      23                 :            :     }
+      24                 :            : 
+      25                 :            :     function aggregate(Call[] memory calls)
+      26                 :            :         public
+      27                 :            :         returns (uint256 blockNumber, bytes[] memory returnData)
+      28                 :            :     {
+      29                 :          0 :         blockNumber = block.number;
+      30                 :          0 :         returnData = new bytes[](calls.length);
+      31                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
+      32                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
+      33         [ #  # ]:          0 :             require(success, "Multicall aggregate: call failed");
+      34                 :          0 :             returnData[i] = ret;
+      35                 :            :         }
+      36                 :            :     }
+      37                 :            : 
+      38                 :            :     function blockAndAggregate(Call[] memory calls)
+      39                 :            :         public
+      40                 :            :         returns (
+      41                 :            :             uint256 blockNumber,
+      42                 :            :             bytes32 blockHash,
+      43                 :            :             Result[] memory returnData
+      44                 :            :         )
+      45                 :            :     {
+      46                 :          0 :         (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
+      47                 :            :     }
+      48                 :            : 
+      49                 :            :     function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
+      50                 :          0 :         blockHash = blockhash(blockNumber);
+      51                 :            :     }
+      52                 :            : 
+      53                 :            :     function getBlockNumber() public view returns (uint256 blockNumber) {
+      54                 :          0 :         blockNumber = block.number;
+      55                 :            :     }
+      56                 :            : 
+      57                 :            :     function getCurrentBlockCoinbase() public view returns (address coinbase) {
+      58                 :          0 :         coinbase = block.coinbase;
+      59                 :            :     }
+      60                 :            : 
+      61                 :            :     function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
+      62                 :          0 :         difficulty = block.difficulty;
+      63                 :            :     }
+      64                 :            : 
+      65                 :            :     function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
+      66                 :          0 :         gaslimit = block.gaslimit;
+      67                 :            :     }
+      68                 :            : 
+      69                 :            :     function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
+      70                 :          0 :         timestamp = block.timestamp;
+      71                 :            :     }
+      72                 :            : 
+      73                 :            :     function getEthBalance(address addr) public view returns (uint256 balance) {
+      74                 :          0 :         balance = addr.balance;
+      75                 :            :     }
+      76                 :            : 
+      77                 :            :     function getLastBlockHash() public view returns (bytes32 blockHash) {
+      78                 :          0 :         blockHash = blockhash(block.number - 1);
+      79                 :            :     }
+      80                 :            : 
+      81                 :            :     function tryAggregateGasRation(bool requireSuccess, Call[] memory calls)
+      82                 :            :         public
+      83                 :            :         returns (Result[] memory returnData)
+      84                 :            :     {
+      85                 :          0 :         returnData = new Result[](calls.length);
+      86                 :          0 :         uint256 gasPerCall = gasleft() / calls.length;
+      87                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
+      88                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call{
+      89                 :            :                 gas: gasleft() > gasPerCall ? gasPerCall : gasleft()
+      90                 :            :             }(calls[i].callData);
+      91                 :            : 
+      92         [ #  # ]:          0 :             if (requireSuccess) {
+      93         [ #  # ]:          0 :                 require(success, "Multicall2 aggregate: call failed");
+      94                 :            :             }
+      95                 :            : 
+      96                 :          0 :             returnData[i] = Result(success, ret);
+      97                 :            :         }
+      98                 :            :     }
+      99                 :            : 
+     100                 :            :     function tryAggregate(bool requireSuccess, Call[] memory calls)
+     101                 :            :         public
+     102                 :            :         returns (Result[] memory returnData)
+     103                 :            :     {
+     104                 :          0 :         returnData = new Result[](calls.length);
+     105                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
+     106                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
+     107                 :            : 
+     108         [ #  # ]:          0 :             if (requireSuccess) {
+     109         [ #  # ]:          0 :                 require(success, "Multicall2 aggregate: call failed");
+     110                 :            :             }
+     111                 :            : 
+     112                 :          0 :             returnData[i] = Result(success, ret);
+     113                 :            :         }
+     114                 :            :     }
+     115                 :            : 
+     116                 :            :     function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)
+     117                 :            :         public
+     118                 :            :         returns (
+     119                 :            :             uint256 blockNumber,
+     120                 :            :             bytes32 blockHash,
+     121                 :            :             Result[] memory returnData
+     122                 :            :         )
+     123                 :            :     {
+     124                 :          0 :         blockNumber = block.number;
+     125                 :          0 :         blockHash = blockhash(block.number);
+     126                 :          0 :         returnData = tryAggregate(requireSuccess, calls);
+     127                 :            :     }
+     128                 :            : }
+     129                 :            : 
+     130                 :            : /// @title Arbitrum Multicall2 - Multicall2 contracts with L1 and L2 block numbers
+     131                 :            : contract ArbMulticall2 {
+     132                 :            :     struct Call {
+     133                 :            :         address target;
+     134                 :            :         bytes callData;
+     135                 :            :     }
+     136                 :            :     struct Result {
+     137                 :            :         bool success;
+     138                 :            :         bytes returnData;
+     139                 :            :     }
+     140                 :            : 
+     141                 :            :     function aggregate(Call[] memory calls)
+     142                 :            :         public
+     143                 :            :         returns (uint256 blockNumber, bytes[] memory returnData)
+     144                 :            :     {
+     145                 :          0 :         blockNumber = ArbSys(address(100)).arbBlockNumber();
+     146                 :          0 :         returnData = new bytes[](calls.length);
+     147                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
+     148                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
+     149         [ #  # ]:          0 :             require(success, "Multicall aggregate: call failed");
+     150                 :          0 :             returnData[i] = ret;
+     151                 :            :         }
+     152                 :            :     }
+     153                 :            : 
+     154                 :            :     function blockAndAggregate(Call[] memory calls)
+     155                 :            :         public
+     156                 :            :         returns (
+     157                 :            :             uint256 blockNumber,
+     158                 :            :             bytes32 blockHash,
+     159                 :            :             Result[] memory returnData
+     160                 :            :         )
+     161                 :            :     {
+     162                 :          0 :         (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
+     163                 :            :     }
+     164                 :            : 
+     165                 :            :     function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
+     166                 :          0 :         blockHash = blockhash(blockNumber);
+     167                 :            :     }
+     168                 :            : 
+     169                 :            :     function getBlockNumber() public view returns (uint256 blockNumber) {
+     170                 :          0 :         blockNumber = ArbSys(address(100)).arbBlockNumber();
+     171                 :            :     }
+     172                 :            : 
+     173                 :            :     function getL1BlockNumber() public view returns (uint256 l1BlockNumber) {
+     174                 :          0 :         l1BlockNumber = block.number;
+     175                 :            :     }
+     176                 :            : 
+     177                 :            :     function getCurrentBlockCoinbase() public view returns (address coinbase) {
+     178                 :          0 :         coinbase = block.coinbase;
+     179                 :            :     }
+     180                 :            : 
+     181                 :            :     function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
+     182                 :          0 :         difficulty = block.difficulty;
+     183                 :            :     }
+     184                 :            : 
+     185                 :            :     function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
+     186                 :          0 :         gaslimit = block.gaslimit;
+     187                 :            :     }
+     188                 :            : 
+     189                 :            :     function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
+     190                 :          0 :         timestamp = block.timestamp;
+     191                 :            :     }
+     192                 :            : 
+     193                 :            :     function getEthBalance(address addr) public view returns (uint256 balance) {
+     194                 :          0 :         balance = addr.balance;
+     195                 :            :     }
+     196                 :            : 
+     197                 :            :     function getLastBlockHash() public view returns (bytes32 blockHash) {
+     198                 :          0 :         blockHash = blockhash(block.number - 1);
+     199                 :            :     }
+     200                 :            : 
+     201                 :            :     function tryAggregateGasRation(bool requireSuccess, Call[] memory calls)
+     202                 :            :         public
+     203                 :            :         returns (Result[] memory returnData)
+     204                 :            :     {
+     205                 :          0 :         returnData = new Result[](calls.length);
+     206                 :          0 :         uint256 gasPerCall = gasleft() / calls.length;
+     207                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
+     208                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call{
+     209                 :            :                 gas: gasleft() > gasPerCall ? gasPerCall : gasleft()
+     210                 :            :             }(calls[i].callData);
+     211                 :            : 
+     212         [ #  # ]:          0 :             if (requireSuccess) {
+     213         [ #  # ]:          0 :                 require(success, "Multicall2 aggregate: call failed");
+     214                 :            :             }
+     215                 :            : 
+     216                 :          0 :             returnData[i] = Result(success, ret);
+     217                 :            :         }
+     218                 :            :     }
+     219                 :            : 
+     220                 :            :     function tryAggregate(bool requireSuccess, Call[] memory calls)
+     221                 :            :         public
+     222                 :            :         returns (Result[] memory returnData)
+     223                 :            :     {
+     224                 :          0 :         returnData = new Result[](calls.length);
+     225                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
+     226                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
+     227                 :            : 
+     228         [ #  # ]:          0 :             if (requireSuccess) {
+     229         [ #  # ]:          0 :                 require(success, "Multicall2 aggregate: call failed");
+     230                 :            :             }
+     231                 :            : 
+     232                 :          0 :             returnData[i] = Result(success, ret);
+     233                 :            :         }
+     234                 :            :     }
+     235                 :            : 
+     236                 :            :     function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)
+     237                 :            :         public
+     238                 :            :         returns (
+     239                 :            :             uint256 blockNumber,
+     240                 :            :             bytes32 blockHash,
+     241                 :            :             Result[] memory returnData
+     242                 :            :         )
+     243                 :            :     {
+     244                 :          0 :         blockNumber = ArbSys(address(100)).arbBlockNumber();
+     245                 :          0 :         blockHash = blockhash(block.number);
+     246                 :          0 :         returnData = tryAggregate(requireSuccess, calls);
+     247                 :            :     }
+     248                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-b.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-b.html new file mode 100644 index 0000000000..ce3442c84e --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-b.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utilsHitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MulticallV2.sol +
0.0%
+
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-f.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-f.html new file mode 100644 index 0000000000..2d8ce65505 --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-f.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utilsHitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MulticallV2.sol +
0.0%
+
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-l.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-l.html new file mode 100644 index 0000000000..5fa664984d --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-l.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utilsHitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MulticallV2.sol +
0.0%
+
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index.html new file mode 100644 index 0000000000..a5214d9a35 --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utilsHitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MulticallV2.sol +
0.0%
+
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func-sort-c.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func-sort-c.html new file mode 100644 index 0000000000..458f0e5fe3 --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/test-foundry - L1ArbitrumExtendedGateway.t.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TestExitReceiver.onExitTransfer3072
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func.html new file mode 100644 index 0000000000..c85e01fdda --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/test-foundry - L1ArbitrumExtendedGateway.t.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TestExitReceiver.onExitTransfer3072
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.gcov.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.gcov.html new file mode 100644 index 0000000000..d97cc02661 --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.gcov.html @@ -0,0 +1,408 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/test-foundry - L1ArbitrumExtendedGateway.t.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.0;
+       4                 :            : 
+       5                 :            : import "forge-std/Test.sol";
+       6                 :            : import "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol";
+       7                 :            : 
+       8                 :            : abstract contract L1ArbitrumExtendedGatewayTest is Test {
+       9                 :            :     IL1ArbitrumGateway public l1Gateway;
+      10                 :            : 
+      11                 :            :     function test_encodeWithdrawal(uint256 exitNum, address dest) public {
+      12                 :            :         bytes32 encodedWithdrawal = L1ArbitrumExtendedGateway(address(l1Gateway)).encodeWithdrawal(
+      13                 :            :             exitNum,
+      14                 :            :             dest
+      15                 :            :         );
+      16                 :            :         bytes32 expectedEncoding = keccak256(abi.encode(exitNum, dest));
+      17                 :            : 
+      18                 :            :         assertEq(encodedWithdrawal, expectedEncoding, "Invalid encodeWithdrawal");
+      19                 :            :     }
+      20                 :            : 
+      21                 :            :     function test_getExternalCall(uint256 exitNum, address dest, bytes memory data) public {
+      22                 :            :         (address target, bytes memory extData) = L1ArbitrumExtendedGateway(address(l1Gateway))
+      23                 :            :             .getExternalCall(exitNum, dest, data);
+      24                 :            : 
+      25                 :            :         assertEq(target, dest, "Invalid dest");
+      26                 :            :         assertEq(extData, data, "Invalid data");
+      27                 :            : 
+      28                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, dest));
+      29                 :            :         (bool isExit, address newTo, bytes memory newData) = L1ArbitrumExtendedGateway(
+      30                 :            :             address(l1Gateway)
+      31                 :            :         ).redirectedExits(exitId);
+      32                 :            :         assertEq(isExit, false, "Invalid isExit");
+      33                 :            :         assertEq(newTo, address(0), "Invalid _newTo");
+      34                 :            :         assertEq(newData.length, 0, "Invalid _newData");
+      35                 :            :     }
+      36                 :            : 
+      37                 :            :     function test_getExternalCall_Redirected(
+      38                 :            :         uint256 exitNum,
+      39                 :            :         address initialDest,
+      40                 :            :         address newDest,
+      41                 :            :         bytes memory data
+      42                 :            :     ) public {
+      43                 :            :         // redirect
+      44                 :            :         vm.prank(initialDest);
+      45                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+      46                 :            :             exitNum,
+      47                 :            :             initialDest,
+      48                 :            :             newDest,
+      49                 :            :             "",
+      50                 :            :             ""
+      51                 :            :         );
+      52                 :            : 
+      53                 :            :         // check getExternalCall returns new destination
+      54                 :            :         (address target, bytes memory extData) = L1ArbitrumExtendedGateway(address(l1Gateway))
+      55                 :            :             .getExternalCall(exitNum, initialDest, "");
+      56                 :            :         assertEq(target, newDest, "Invalid dest");
+      57                 :            :         assertEq(extData.length, 0, "Invalid data");
+      58                 :            : 
+      59                 :            :         // check exit redirection is properly stored
+      60                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDest));
+      61                 :            :         (bool isExit, address newTo, bytes memory newData) = L1ArbitrumExtendedGateway(
+      62                 :            :             address(l1Gateway)
+      63                 :            :         ).redirectedExits(exitId);
+      64                 :            :         assertEq(isExit, true, "Invalid isExit");
+      65                 :            :         assertEq(newTo, newDest, "Invalid _newTo");
+      66                 :            :         assertEq(newData.length, 0, "Invalid _newData");
+      67                 :            :     }
+      68                 :            : 
+      69                 :            :     function test_transferExitAndCall_EmptyData_NotRedirected(
+      70                 :            :         uint256 exitNum,
+      71                 :            :         address initialDestination,
+      72                 :            :         address newDestination
+      73                 :            :     ) public {
+      74                 :            :         bytes memory newData;
+      75                 :            :         bytes memory data;
+      76                 :            : 
+      77                 :            :         // check event
+      78                 :            :         vm.expectEmit(true, true, true, true);
+      79                 :            :         emit WithdrawRedirected(initialDestination, newDestination, exitNum, newData, data, false);
+      80                 :            : 
+      81                 :            :         // do it
+      82                 :            :         vm.prank(initialDestination);
+      83                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+      84                 :            :             exitNum,
+      85                 :            :             initialDestination,
+      86                 :            :             newDestination,
+      87                 :            :             newData,
+      88                 :            :             data
+      89                 :            :         );
+      90                 :            : 
+      91                 :            :         // check exit data is properly updated
+      92                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination));
+      93                 :            :         (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway(
+      94                 :            :             address(l1Gateway)
+      95                 :            :         ).redirectedExits(exitId);
+      96                 :            :         assertEq(isExit, true, "Invalid isExit");
+      97                 :            :         assertEq(exitTo, newDestination, "Invalid exitTo");
+      98                 :            :         assertEq(exitData.length, 0, "Invalid exitData");
+      99                 :            :     }
+     100                 :            : 
+     101                 :            :     function test_transferExitAndCall_EmptyData_Redirected(
+     102                 :            :         uint256 exitNum,
+     103                 :            :         address initialDestination
+     104                 :            :     ) public {
+     105                 :            :         bytes memory data;
+     106                 :            :         address intermediateDestination = address(new TestExitReceiver());
+     107                 :            : 
+     108                 :            :         // transfer exit
+     109                 :            :         vm.prank(initialDestination);
+     110                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     111                 :            :             exitNum,
+     112                 :            :             initialDestination,
+     113                 :            :             intermediateDestination,
+     114                 :            :             "",
+     115                 :            :             data
+     116                 :            :         );
+     117                 :            : 
+     118                 :            :         address finalDestination = address(new TestExitReceiver());
+     119                 :            :         vm.prank(intermediateDestination);
+     120                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     121                 :            :             exitNum,
+     122                 :            :             initialDestination,
+     123                 :            :             finalDestination,
+     124                 :            :             "",
+     125                 :            :             data
+     126                 :            :         );
+     127                 :            : 
+     128                 :            :         // check exit data is properly updated
+     129                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination));
+     130                 :            :         (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway(
+     131                 :            :             address(l1Gateway)
+     132                 :            :         ).redirectedExits(exitId);
+     133                 :            :         assertEq(isExit, true, "Invalid isExit");
+     134                 :            :         assertEq(exitTo, finalDestination, "Invalid exitTo");
+     135                 :            :         assertEq(exitData.length, 0, "Invalid exitData");
+     136                 :            :     }
+     137                 :            : 
+     138                 :            :     function test_transferExitAndCall_NonEmptyData(
+     139                 :            :         uint256 exitNum,
+     140                 :            :         address initialDestination
+     141                 :            :     ) public {
+     142                 :            :         bytes memory newData;
+     143                 :            :         bytes memory data = abi.encode("fun()");
+     144                 :            :         address newDestination = address(new TestExitReceiver());
+     145                 :            : 
+     146                 :            :         // check events
+     147                 :            :         vm.expectEmit(true, true, true, true);
+     148                 :            :         emit ExitHookTriggered(initialDestination, exitNum, data);
+     149                 :            : 
+     150                 :            :         vm.expectEmit(true, true, true, true);
+     151                 :            :         emit WithdrawRedirected(initialDestination, newDestination, exitNum, newData, data, true);
+     152                 :            : 
+     153                 :            :         // do it
+     154                 :            :         vm.prank(initialDestination);
+     155                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     156                 :            :             exitNum,
+     157                 :            :             initialDestination,
+     158                 :            :             newDestination,
+     159                 :            :             newData,
+     160                 :            :             data
+     161                 :            :         );
+     162                 :            : 
+     163                 :            :         // check exit data is properly updated
+     164                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination));
+     165                 :            :         (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway(
+     166                 :            :             address(l1Gateway)
+     167                 :            :         ).redirectedExits(exitId);
+     168                 :            :         assertEq(isExit, true, "Invalid isExit");
+     169                 :            :         assertEq(exitTo, newDestination, "Invalid exitTo");
+     170                 :            :         assertEq(exitData.length, 0, "Invalid exitData");
+     171                 :            :     }
+     172                 :            : 
+     173                 :            :     function test_transferExitAndCall_NonEmptyData_Redirected(
+     174                 :            :         uint256 exitNum,
+     175                 :            :         address initialDestination
+     176                 :            :     ) public {
+     177                 :            :         bytes memory data = abi.encode("run()");
+     178                 :            :         address intermediateDestination = address(new TestExitReceiver());
+     179                 :            : 
+     180                 :            :         // transfer exit
+     181                 :            :         vm.prank(initialDestination);
+     182                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     183                 :            :             exitNum,
+     184                 :            :             initialDestination,
+     185                 :            :             intermediateDestination,
+     186                 :            :             "",
+     187                 :            :             data
+     188                 :            :         );
+     189                 :            : 
+     190                 :            :         address finalDestination = address(new TestExitReceiver());
+     191                 :            :         vm.prank(intermediateDestination);
+     192                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     193                 :            :             exitNum,
+     194                 :            :             initialDestination,
+     195                 :            :             finalDestination,
+     196                 :            :             "",
+     197                 :            :             data
+     198                 :            :         );
+     199                 :            : 
+     200                 :            :         // check exit data is properly updated
+     201                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination));
+     202                 :            :         (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway(
+     203                 :            :             address(l1Gateway)
+     204                 :            :         ).redirectedExits(exitId);
+     205                 :            :         assertEq(isExit, true, "Invalid isExit");
+     206                 :            :         assertEq(exitTo, finalDestination, "Invalid exitTo");
+     207                 :            :         assertEq(exitData.length, 0, "Invalid exitData");
+     208                 :            :     }
+     209                 :            : 
+     210                 :            :     function test_transferExitAndCall_revert_NotExpectedSender() public {
+     211                 :            :         address nonSender = address(800);
+     212                 :            :         vm.expectRevert("NOT_EXPECTED_SENDER");
+     213                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     214                 :            :             4,
+     215                 :            :             nonSender,
+     216                 :            :             address(2),
+     217                 :            :             "",
+     218                 :            :             ""
+     219                 :            :         );
+     220                 :            :     }
+     221                 :            : 
+     222                 :            :     function test_transferExitAndCall_revert_NoDataAllowed() public {
+     223                 :            :         bytes memory nonEmptyData = bytes("abc");
+     224                 :            :         vm.prank(address(1));
+     225                 :            :         vm.expectRevert("NO_DATA_ALLOWED");
+     226                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     227                 :            :             4,
+     228                 :            :             address(1),
+     229                 :            :             address(2),
+     230                 :            :             nonEmptyData,
+     231                 :            :             ""
+     232                 :            :         );
+     233                 :            :     }
+     234                 :            : 
+     235                 :            :     function test_transferExitAndCall_revert_ToNotContract(address initialDestination) public {
+     236                 :            :         bytes memory data = abi.encode("execute()");
+     237                 :            :         address nonContractNewDestination = address(15);
+     238                 :            : 
+     239                 :            :         vm.prank(initialDestination);
+     240                 :            :         vm.expectRevert("TO_NOT_CONTRACT");
+     241                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     242                 :            :             4,
+     243                 :            :             initialDestination,
+     244                 :            :             nonContractNewDestination,
+     245                 :            :             "",
+     246                 :            :             data
+     247                 :            :         );
+     248                 :            :     }
+     249                 :            : 
+     250                 :            :     function test_transferExitAndCall_revert_TransferHookFail(
+     251                 :            :         uint256 exitNum,
+     252                 :            :         address initialDestination
+     253                 :            :     ) public {
+     254                 :            :         bytes memory data = abi.encode("failIt");
+     255                 :            :         address newDestination = address(new TestExitReceiver());
+     256                 :            : 
+     257                 :            :         vm.prank(initialDestination);
+     258                 :            :         vm.expectRevert("TRANSFER_HOOK_FAIL");
+     259                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     260                 :            :             exitNum,
+     261                 :            :             initialDestination,
+     262                 :            :             newDestination,
+     263                 :            :             "",
+     264                 :            :             data
+     265                 :            :         );
+     266                 :            :     }
+     267                 :            : 
+     268                 :            :     function test_transferExitAndCall_revert_TransferHookFail_Redirected(
+     269                 :            :         uint256 exitNum,
+     270                 :            :         address initialDestination
+     271                 :            :     ) public {
+     272                 :            :         bytes memory data = abi.encode("abc");
+     273                 :            :         address intermediateDestination = address(new TestExitReceiver());
+     274                 :            : 
+     275                 :            :         vm.prank(initialDestination);
+     276                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     277                 :            :             exitNum,
+     278                 :            :             initialDestination,
+     279                 :            :             intermediateDestination,
+     280                 :            :             "",
+     281                 :            :             data
+     282                 :            :         );
+     283                 :            : 
+     284                 :            :         bytes memory failData = abi.encode("failIt");
+     285                 :            :         address finalDestination = address(new TestExitReceiver());
+     286                 :            : 
+     287                 :            :         vm.prank(intermediateDestination);
+     288                 :            :         vm.expectRevert("TRANSFER_HOOK_FAIL");
+     289                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
+     290                 :            :             exitNum,
+     291                 :            :             initialDestination,
+     292                 :            :             finalDestination,
+     293                 :            :             "",
+     294                 :            :             failData
+     295                 :            :         );
+     296                 :            :     }
+     297                 :            : 
+     298                 :            :     /////
+     299                 :            :     /// Event declarations
+     300                 :            :     /////
+     301                 :            :     event WithdrawRedirected(
+     302                 :            :         address indexed from,
+     303                 :            :         address indexed to,
+     304                 :            :         uint256 indexed exitNum,
+     305                 :            :         bytes newData,
+     306                 :            :         bytes data,
+     307                 :            :         bool madeExternalCall
+     308                 :            :     );
+     309                 :            :     event ExitHookTriggered(address sender, uint256 exitNum, bytes data);
+     310                 :            : }
+     311                 :            : 
+     312                 :            : contract TestExitReceiver is ITradeableExitReceiver {
+     313                 :            :     event ExitHookTriggered(address sender, uint256 exitNum, bytes data);
+     314                 :            : 
+     315                 :            :     function onExitTransfer(
+     316                 :            :         address sender,
+     317                 :            :         uint256 exitNum,
+     318                 :            :         bytes calldata data
+     319                 :            :     ) external override returns (bool) {
+     320                 :       3072 :         emit ExitHookTriggered(sender, exitNum, data);
+     321                 :       3072 :         return keccak256(data) != keccak256(abi.encode("failIt"));
+     322                 :            :     }
+     323                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-b.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-b.html new file mode 100644 index 0000000000..f569a8b36a --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-b.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/test-foundryHitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.t.sol +
100.0%
+
100.0 %2 / 2100.0 %1 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-f.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-f.html new file mode 100644 index 0000000000..a288ffe8ce --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-f.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/test-foundryHitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.t.sol +
100.0%
+
100.0 %2 / 2100.0 %1 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-l.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-l.html new file mode 100644 index 0000000000..86c6d1f9f4 --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-l.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/test-foundryHitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.t.sol +
100.0%
+
100.0 %2 / 2100.0 %1 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index.html new file mode 100644 index 0000000000..d203dff66d --- /dev/null +++ b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/test-foundryHitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.t.sol +
100.0%
+
100.0 %2 / 2100.0 %1 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/amber.png b/coverage/amber.png new file mode 100644 index 0000000000000000000000000000000000000000..2cab170d8359081983a4e343848dfe06bc490f12 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^G2tW}LqE04T&+ z;1OBOz`!j8!i<;h*8KqrvZOouIx;Y9?C1WI$O`1M1^9%x{(levWG + + + + + + LCOV - lcov.info - arbitrum/L2ArbitrumMessenger.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum - L2ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2ArbitrumMessenger.sendTxToL10
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/L2ArbitrumMessenger.sol.func.html b/coverage/arbitrum/L2ArbitrumMessenger.sol.func.html new file mode 100644 index 0000000000..93a5b96bec --- /dev/null +++ b/coverage/arbitrum/L2ArbitrumMessenger.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - arbitrum/L2ArbitrumMessenger.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum - L2ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2ArbitrumMessenger.sendTxToL10
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/L2ArbitrumMessenger.sol.gcov.html b/coverage/arbitrum/L2ArbitrumMessenger.sol.gcov.html new file mode 100644 index 0000000000..7741c7522d --- /dev/null +++ b/coverage/arbitrum/L2ArbitrumMessenger.sol.gcov.html @@ -0,0 +1,125 @@ + + + + + + + LCOV - lcov.info - arbitrum/L2ArbitrumMessenger.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum - L2ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol";
+      22                 :            : 
+      23                 :            : /// @notice L2 utility contract to assist with L1 <=> L2 interactions
+      24                 :            : /// @dev this is an abstract contract instead of library so the functions can be easily overriden when testing
+      25                 :            : abstract contract L2ArbitrumMessenger {
+      26                 :            :     address internal constant ARB_SYS_ADDRESS = address(100);
+      27                 :            : 
+      28                 :            :     event TxToL1(address indexed _from, address indexed _to, uint256 indexed _id, bytes _data);
+      29                 :            : 
+      30                 :            :     function sendTxToL1(
+      31                 :            :         uint256 _l1CallValue,
+      32                 :            :         address _from,
+      33                 :            :         address _to,
+      34                 :            :         bytes memory _data
+      35                 :            :     ) internal returns (uint256) {
+      36                 :          0 :         uint256 _id = ArbSys(ARB_SYS_ADDRESS).sendTxToL1{ value: _l1CallValue }(_to, _data);
+      37                 :          0 :         emit TxToL1(_from, _to, _id, _data);
+      38                 :          0 :         return _id;
+      39                 :            :     }
+      40                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/ReverseArbToken.sol.func-sort-c.html b/coverage/arbitrum/ReverseArbToken.sol.func-sort-c.html new file mode 100644 index 0000000000..06f50d3577 --- /dev/null +++ b/coverage/arbitrum/ReverseArbToken.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - arbitrum/ReverseArbToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum - ReverseArbToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ReverseArbToken.bridgeBurn0
ReverseArbToken.bridgeMint0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/ReverseArbToken.sol.func.html b/coverage/arbitrum/ReverseArbToken.sol.func.html new file mode 100644 index 0000000000..6bcf45ee3c --- /dev/null +++ b/coverage/arbitrum/ReverseArbToken.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - arbitrum/ReverseArbToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum - ReverseArbToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ReverseArbToken.bridgeBurn0
ReverseArbToken.bridgeMint0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/ReverseArbToken.sol.gcov.html b/coverage/arbitrum/ReverseArbToken.sol.gcov.html new file mode 100644 index 0000000000..041bc21e2b --- /dev/null +++ b/coverage/arbitrum/ReverseArbToken.sol.gcov.html @@ -0,0 +1,125 @@ + + + + + + + LCOV - lcov.info - arbitrum/ReverseArbToken.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum - ReverseArbToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : // solhint-disable-next-line compiler-version
+      20                 :            : pragma solidity >=0.6.9 <0.9.0;
+      21                 :            : 
+      22                 :            : import "./IArbToken.sol";
+      23                 :            : 
+      24                 :            : /// @title  Minimum expected interface for L2 token that interacts with the reverse L2 token bridge (this is the interface necessary
+      25                 :            : ///         for a custom token that interacts with the reverse gateway, see TestArbCustomToken.sol for an example implementation).
+      26                 :            : /// @dev    The L2ArbitrumGateway expects objects of type IArbToken, which includes
+      27                 :            : ///         bridgeMint/burn. However when the L2ReverseCustomGateway overrides the functions
+      28                 :            : ///         that make use of bridgeMint/burn and replaces them with safeTransfer/from.
+      29                 :            : ///         We inherit IArbToken so that we fulfil the interface L2ArbitrumGateway expects
+      30                 :            : ///         but since we know that bridgeMint/burn won't/shouldn't be used we override these
+      31                 :            : ///         functions to ensure that if they throw if called during development
+      32                 :            : abstract contract ReverseArbToken is IArbToken {
+      33                 :            :     function bridgeMint(address, uint256) public override {
+      34                 :          0 :         revert("BRIDGE_MINT_NOT_IMPLEMENTED");
+      35                 :            :     }
+      36                 :            : 
+      37                 :            :     function bridgeBurn(address, uint256) public override {
+      38                 :          0 :         revert("BRIDGE_BURN_NOT_IMPLEMENTED");
+      39                 :            :     }
+      40                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/StandardArbERC20.sol.func-sort-c.html b/coverage/arbitrum/StandardArbERC20.sol.func-sort-c.html new file mode 100644 index 0000000000..c006309896 --- /dev/null +++ b/coverage/arbitrum/StandardArbERC20.sol.func-sort-c.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - arbitrum/StandardArbERC20.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum - StandardArbERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
StandardArbERC20.bridgeInit0
StandardArbERC20.decimals0
StandardArbERC20.name0
StandardArbERC20.symbol0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/StandardArbERC20.sol.func.html b/coverage/arbitrum/StandardArbERC20.sol.func.html new file mode 100644 index 0000000000..ae8ab8bd34 --- /dev/null +++ b/coverage/arbitrum/StandardArbERC20.sol.func.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - arbitrum/StandardArbERC20.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum - StandardArbERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
StandardArbERC20.bridgeInit0
StandardArbERC20.decimals0
StandardArbERC20.name0
StandardArbERC20.symbol0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/StandardArbERC20.sol.gcov.html b/coverage/arbitrum/StandardArbERC20.sol.gcov.html new file mode 100644 index 0000000000..c3ca0b1f33 --- /dev/null +++ b/coverage/arbitrum/StandardArbERC20.sol.gcov.html @@ -0,0 +1,183 @@ + + + + + + + LCOV - lcov.info - arbitrum/StandardArbERC20.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum - StandardArbERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:060.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../libraries/Cloneable.sol";
+      22                 :            : import "../libraries/L2GatewayToken.sol";
+      23                 :            : import "../libraries/BytesParser.sol";
+      24                 :            : import "./IArbToken.sol";
+      25                 :            : 
+      26                 :            : /**
+      27                 :            :  * @title Standard (i.e., non-custom) contract deployed by L2Gateway.sol as L2 ERC20. Includes standard ERC20 interface plus additional methods for deposits/withdraws
+      28                 :            :  */
+      29                 :            : contract StandardArbERC20 is IArbToken, L2GatewayToken, Cloneable {
+      30                 :            :     struct ERC20Getters {
+      31                 :            :         bool ignoreDecimals;
+      32                 :            :         bool ignoreName;
+      33                 :            :         bool ignoreSymbol;
+      34                 :            :     }
+      35                 :            :     ERC20Getters private availableGetters;
+      36                 :            : 
+      37                 :            :     /**
+      38                 :            :      * @notice initialize the token
+      39                 :            :      * @dev the L2 bridge assumes this does not fail or revert
+      40                 :            :      * @param _l1Address L1 address of ERC20
+      41                 :            :      * @param _data encoded symbol/name/decimal data for initial deploy
+      42                 :            :      */
+      43                 :            :     function bridgeInit(address _l1Address, bytes memory _data) public virtual {
+      44                 :          0 :         (bytes memory name_, bytes memory symbol_, bytes memory decimals_) = abi.decode(
+      45                 :            :             _data,
+      46                 :            :             (bytes, bytes, bytes)
+      47                 :            :         );
+      48                 :            :         // what if decode reverts? shouldn't as this is encoded by L1 contract
+      49                 :            : 
+      50                 :            :         /*
+      51                 :            :          *  if parsing fails, the type's default value gets assigned
+      52                 :            :          *  the parsing can fail for different reasons:
+      53                 :            :          *      1. method not available in L1 (empty input)
+      54                 :            :          *      2. data type is encoded differently in the L1 (trying to abi decode the wrong data type)
+      55                 :            :          *  currently (1) returns a parser fails and (2) reverts as there is no `abi.tryDecode`
+      56                 :            :          *  https://github.com/ethereum/solidity/issues/10381
+      57                 :            :          */
+      58                 :            : 
+      59                 :          0 :         (bool parseNameSuccess, string memory parsedName) = BytesParser.toString(name_);
+      60                 :          0 :         (bool parseSymbolSuccess, string memory parsedSymbol) = BytesParser.toString(symbol_);
+      61                 :          0 :         (bool parseDecimalSuccess, uint8 parsedDecimals) = BytesParser.toUint8(decimals_);
+      62                 :            : 
+      63                 :          0 :         L2GatewayToken._initialize(
+      64                 :            :             parsedName,
+      65                 :            :             parsedSymbol,
+      66                 :            :             parsedDecimals,
+      67                 :            :             msg.sender, // _l2Gateway,
+      68                 :            :             _l1Address // _l1Counterpart
+      69                 :            :         );
+      70                 :            : 
+      71                 :            :         // here we assume that (2) would have reverted, so if the parser failed its because the getter isn't available in the L1.
+      72                 :            :         // instead of storing on a struct, we could instead set a magic number, at something like `type(uint8).max` or random string
+      73                 :            :         // to be more general we instead use an extra storage slot
+      74                 :          0 :         availableGetters = ERC20Getters({
+      75                 :            :             ignoreName: !parseNameSuccess,
+      76                 :            :             ignoreSymbol: !parseSymbolSuccess,
+      77                 :            :             ignoreDecimals: !parseDecimalSuccess
+      78                 :            :         });
+      79                 :            :     }
+      80                 :            : 
+      81                 :            :     function decimals() public view override returns (uint8) {
+      82                 :            :         // no revert message just as in the L1 if you called and the function is not implemented
+      83         [ #  # ]:          0 :         if (availableGetters.ignoreDecimals) revert();
+      84                 :          0 :         return super.decimals();
+      85                 :            :     }
+      86                 :            : 
+      87                 :            :     function name() public view override returns (string memory) {
+      88                 :            :         // no revert message just as in the L1 if you called and the function is not implemented
+      89         [ #  # ]:          0 :         if (availableGetters.ignoreName) revert();
+      90                 :          0 :         return super.name();
+      91                 :            :     }
+      92                 :            : 
+      93                 :            :     function symbol() public view override returns (string memory) {
+      94                 :            :         // no revert message just as in the L1 if you called and the function is not implemented
+      95         [ #  # ]:          0 :         if (availableGetters.ignoreSymbol) revert();
+      96                 :          0 :         return super.symbol();
+      97                 :            :     }
+      98                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..d0f6076984 --- /dev/null +++ b/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func-sort-c.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2ArbitrumGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0510.0 %
Date:2023-04-27 16:26:32Functions:090.0 %
Branches:0260.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2ArbitrumGateway._initialize0
L2ArbitrumGateway.createOutboundTx0
L2ArbitrumGateway.finalizeInboundTransfer0
L2ArbitrumGateway.getOutboundCalldata0
L2ArbitrumGateway.inboundEscrowTransfer0
L2ArbitrumGateway.outboundEscrowTransfer0
L2ArbitrumGateway.outboundTransfer0
L2ArbitrumGateway.postUpgradeInit0
L2ArbitrumGateway.triggerWithdrawal0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func.html b/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func.html new file mode 100644 index 0000000000..974962a754 --- /dev/null +++ b/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2ArbitrumGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0510.0 %
Date:2023-04-27 16:26:32Functions:090.0 %
Branches:0260.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2ArbitrumGateway._initialize0
L2ArbitrumGateway.createOutboundTx0
L2ArbitrumGateway.finalizeInboundTransfer0
L2ArbitrumGateway.getOutboundCalldata0
L2ArbitrumGateway.inboundEscrowTransfer0
L2ArbitrumGateway.outboundEscrowTransfer0
L2ArbitrumGateway.outboundTransfer0
L2ArbitrumGateway.postUpgradeInit0
L2ArbitrumGateway.triggerWithdrawal0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.gcov.html b/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.gcov.html new file mode 100644 index 0000000000..b32e5cf757 --- /dev/null +++ b/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.gcov.html @@ -0,0 +1,384 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2ArbitrumGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0510.0 %
Date:2023-04-27 16:26:32Functions:090.0 %
Branches:0260.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "@openzeppelin/contracts/utils/Address.sol";
+      22                 :            : import "../../libraries/AddressAliasHelper.sol";
+      23                 :            : import "../../libraries/BytesLib.sol";
+      24                 :            : import "../../libraries/ProxyUtil.sol";
+      25                 :            : 
+      26                 :            : import "../IArbToken.sol";
+      27                 :            : 
+      28                 :            : import "../L2ArbitrumMessenger.sol";
+      29                 :            : import "../../libraries/gateway/GatewayMessageHandler.sol";
+      30                 :            : import "../../libraries/gateway/TokenGateway.sol";
+      31                 :            : 
+      32                 :            : /**
+      33                 :            :  * @title Common interface for gatways on Arbitrum messaging to L1.
+      34                 :            :  */
+      35                 :            : abstract contract L2ArbitrumGateway is L2ArbitrumMessenger, TokenGateway {
+      36                 :            :     using Address for address;
+      37                 :            : 
+      38                 :            :     uint256 public exitNum;
+      39                 :            : 
+      40                 :            :     event DepositFinalized(
+      41                 :            :         address indexed l1Token,
+      42                 :            :         address indexed _from,
+      43                 :            :         address indexed _to,
+      44                 :            :         uint256 _amount
+      45                 :            :     );
+      46                 :            : 
+      47                 :            :     event WithdrawalInitiated(
+      48                 :            :         address l1Token,
+      49                 :            :         address indexed _from,
+      50                 :            :         address indexed _to,
+      51                 :            :         uint256 indexed _l2ToL1Id,
+      52                 :            :         uint256 _exitNum,
+      53                 :            :         uint256 _amount
+      54                 :            :     );
+      55                 :            : 
+      56                 :            :     modifier onlyCounterpartGateway() override {
+      57                 :            :         require(
+      58                 :            :             msg.sender == AddressAliasHelper.applyL1ToL2Alias(counterpartGateway),
+      59                 :            :             "ONLY_COUNTERPART_GATEWAY"
+      60                 :            :         );
+      61                 :            :         _;
+      62                 :            :     }
+      63                 :            : 
+      64                 :            :     function postUpgradeInit() external {
+      65                 :            :         // it is assumed the L2 Arbitrum Gateway contract is behind a Proxy controlled by a proxy admin
+      66                 :            :         // this function can only be called by the proxy admin contract
+      67                 :          0 :         address proxyAdmin = ProxyUtil.getProxyAdmin();
+      68         [ #  # ]:          0 :         require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");
+      69                 :            :         // this has no other logic since the current upgrade doesn't require this logic
+      70                 :            :     }
+      71                 :            : 
+      72                 :            :     function _initialize(address _l1Counterpart, address _router) internal override {
+      73                 :          0 :         TokenGateway._initialize(_l1Counterpart, _router);
+      74                 :            :         // L1 gateway must have a router
+      75         [ #  # ]:          0 :         require(_router != address(0), "BAD_ROUTER");
+      76                 :            :     }
+      77                 :            : 
+      78                 :            :     function createOutboundTx(
+      79                 :            :         address _from,
+      80                 :            :         uint256, /* _tokenAmount */
+      81                 :            :         bytes memory _outboundCalldata
+      82                 :            :     ) internal virtual returns (uint256) {
+      83                 :            :         // We make this function virtual since outboundTransfer logic is the same for many gateways
+      84                 :            :         // but sometimes (ie weth) you construct the outgoing message differently.
+      85                 :            : 
+      86                 :            :         // exitNum incremented after being included in _outboundCalldata
+      87                 :          0 :         exitNum++;
+      88                 :          0 :         return
+      89                 :            :             sendTxToL1(
+      90                 :            :                 // default to sending no callvalue to the L1
+      91                 :            :                 0,
+      92                 :            :                 _from,
+      93                 :            :                 counterpartGateway,
+      94                 :            :                 _outboundCalldata
+      95                 :            :             );
+      96                 :            :     }
+      97                 :            : 
+      98                 :            :     function getOutboundCalldata(
+      99                 :            :         address _token,
+     100                 :            :         address _from,
+     101                 :            :         address _to,
+     102                 :            :         uint256 _amount,
+     103                 :            :         bytes memory _data
+     104                 :            :     ) public view override returns (bytes memory outboundCalldata) {
+     105                 :          0 :         outboundCalldata = abi.encodeWithSelector(
+     106                 :            :             ITokenGateway.finalizeInboundTransfer.selector,
+     107                 :            :             _token,
+     108                 :            :             _from,
+     109                 :            :             _to,
+     110                 :            :             _amount,
+     111                 :            :             GatewayMessageHandler.encodeFromL2GatewayMsg(exitNum, _data)
+     112                 :            :         );
+     113                 :            : 
+     114                 :          0 :         return outboundCalldata;
+     115                 :            :     }
+     116                 :            : 
+     117                 :            :     function outboundTransfer(
+     118                 :            :         address _l1Token,
+     119                 :            :         address _to,
+     120                 :            :         uint256 _amount,
+     121                 :            :         bytes calldata _data
+     122                 :            :     ) public payable returns (bytes memory) {
+     123                 :          0 :         return outboundTransfer(_l1Token, _to, _amount, 0, 0, _data);
+     124                 :            :     }
+     125                 :            : 
+     126                 :            :     /**
+     127                 :            :      * @notice Initiates a token withdrawal from Arbitrum to Ethereum
+     128                 :            :      * @param _l1Token l1 address of token
+     129                 :            :      * @param _to destination address
+     130                 :            :      * @param _amount amount of tokens withdrawn
+     131                 :            :      * @return res encoded unique identifier for withdrawal
+     132                 :            :      */
+     133                 :            :     function outboundTransfer(
+     134                 :            :         address _l1Token,
+     135                 :            :         address _to,
+     136                 :            :         uint256 _amount,
+     137                 :            :         uint256, /* _maxGas */
+     138                 :            :         uint256, /* _gasPriceBid */
+     139                 :            :         bytes calldata _data
+     140                 :            :     ) public payable override returns (bytes memory res) {
+     141                 :            :         // This function is set as public and virtual so that subclasses can override
+     142                 :            :         // it and add custom validation for callers (ie only whitelisted users)
+     143                 :            : 
+     144                 :            :         // the function is marked as payable to conform to the inheritance setup
+     145                 :            :         // this particular code path shouldn't have a msg.value > 0
+     146                 :            :         // TODO: remove this invariant for execution markets
+     147         [ #  # ]:          0 :         require(msg.value == 0, "NO_VALUE");
+     148                 :            : 
+     149                 :          0 :         address _from;
+     150                 :          0 :         bytes memory _extraData;
+     151                 :            :         {
+     152         [ #  # ]:          0 :             if (isRouter(msg.sender)) {
+     153                 :          0 :                 (_from, _extraData) = GatewayMessageHandler.parseFromRouterToGateway(_data);
+     154                 :            :             } else {
+     155                 :          0 :                 _from = msg.sender;
+     156                 :          0 :                 _extraData = _data;
+     157                 :            :             }
+     158                 :            :         }
+     159                 :            :         // the inboundEscrowAndCall functionality has been disabled, so no data is allowed
+     160         [ #  # ]:          0 :         require(_extraData.length == 0, "EXTRA_DATA_DISABLED");
+     161                 :            : 
+     162                 :          0 :         uint256 id;
+     163                 :            :         {
+     164                 :          0 :             address l2Token = calculateL2TokenAddress(_l1Token);
+     165         [ #  # ]:          0 :             require(l2Token.isContract(), "TOKEN_NOT_DEPLOYED");
+     166         [ #  # ]:          0 :             require(IArbToken(l2Token).l1Address() == _l1Token, "NOT_EXPECTED_L1_TOKEN");
+     167                 :            : 
+     168                 :          0 :             _amount = outboundEscrowTransfer(l2Token, _from, _amount);
+     169                 :          0 :             id = triggerWithdrawal(_l1Token, _from, _to, _amount, _extraData);
+     170                 :            :         }
+     171                 :          0 :         return abi.encode(id);
+     172                 :            :     }
+     173                 :            : 
+     174                 :            :     function triggerWithdrawal(
+     175                 :            :         address _l1Token,
+     176                 :            :         address _from,
+     177                 :            :         address _to,
+     178                 :            :         uint256 _amount,
+     179                 :            :         bytes memory _data
+     180                 :            :     ) internal returns (uint256) {
+     181                 :            :         // exit number used for tradeable exits
+     182                 :          0 :         uint256 currExitNum = exitNum;
+     183                 :            :         // unique id used to identify the L2 to L1 tx
+     184                 :          0 :         uint256 id = createOutboundTx(
+     185                 :            :             _from,
+     186                 :            :             _amount,
+     187                 :            :             getOutboundCalldata(_l1Token, _from, _to, _amount, _data)
+     188                 :            :         );
+     189                 :          0 :         emit WithdrawalInitiated(_l1Token, _from, _to, id, currExitNum, _amount);
+     190                 :          0 :         return id;
+     191                 :            :     }
+     192                 :            : 
+     193                 :            :     function outboundEscrowTransfer(
+     194                 :            :         address _l2Token,
+     195                 :            :         address _from,
+     196                 :            :         uint256 _amount
+     197                 :            :     ) internal virtual returns (uint256 amountBurnt) {
+     198                 :            :         // this method is virtual since different subclasses can handle escrow differently
+     199                 :            :         // user funds are escrowed on the gateway using this function
+     200                 :            :         // burns L2 tokens in order to release escrowed L1 tokens
+     201                 :          0 :         IArbToken(_l2Token).bridgeBurn(_from, _amount);
+     202                 :            :         // by default we assume that the amount we send to bridgeBurn is the amount burnt
+     203                 :            :         // this might not be the case for every token
+     204                 :          0 :         return _amount;
+     205                 :            :     }
+     206                 :            : 
+     207                 :            :     function inboundEscrowTransfer(
+     208                 :            :         address _l2Address,
+     209                 :            :         address _dest,
+     210                 :            :         uint256 _amount
+     211                 :            :     ) internal virtual {
+     212                 :            :         // this method is virtual since different subclasses can handle escrow differently
+     213                 :          0 :         IArbToken(_l2Address).bridgeMint(_dest, _amount);
+     214                 :            :     }
+     215                 :            : 
+     216                 :            :     /**
+     217                 :            :      * @notice Mint on L2 upon L1 deposit.
+     218                 :            :      * If token not yet deployed and symbol/name/decimal data is included, deploys StandardArbERC20
+     219                 :            :      * @dev Callable only by the L1ERC20Gateway.outboundTransfer method. For initial deployments of a token the L1 L1ERC20Gateway
+     220                 :            :      * is expected to include the deployData. If not a L1 withdrawal is automatically triggered for the user
+     221                 :            :      * @param _token L1 address of ERC20
+     222                 :            :      * @param _from account that initiated the deposit in the L1
+     223                 :            :      * @param _to account to be credited with the tokens in the L2 (can be the user's L2 account or a contract)
+     224                 :            :      * @param _amount token amount to be minted to the user
+     225                 :            :      * @param _data encoded symbol/name/decimal data for deploy, in addition to any additional callhook data
+     226                 :            :      */
+     227                 :            :     function finalizeInboundTransfer(
+     228                 :            :         address _token,
+     229                 :            :         address _from,
+     230                 :            :         address _to,
+     231                 :            :         uint256 _amount,
+     232                 :            :         bytes calldata _data
+     233                 :            :     ) external payable override onlyCounterpartGateway {
+     234                 :          0 :         (bytes memory gatewayData, bytes memory callHookData) = GatewayMessageHandler
+     235                 :            :             .parseFromL1GatewayMsg(_data);
+     236                 :            : 
+     237         [ #  # ]:          0 :         if (callHookData.length != 0) {
+     238                 :            :             // callHookData should always be 0 since inboundEscrowAndCall is disabled
+     239                 :          0 :             callHookData = bytes("");
+     240                 :            :         }
+     241                 :            : 
+     242                 :          0 :         address expectedAddress = calculateL2TokenAddress(_token);
+     243                 :            : 
+     244         [ #  # ]:          0 :         if (!expectedAddress.isContract()) {
+     245                 :          0 :             bool shouldHalt = handleNoContract(
+     246                 :            :                 _token,
+     247                 :            :                 expectedAddress,
+     248                 :            :                 _from,
+     249                 :            :                 _to,
+     250                 :            :                 _amount,
+     251                 :            :                 gatewayData
+     252                 :            :             );
+     253         [ #  # ]:          0 :             if (shouldHalt) return;
+     254                 :            :         }
+     255                 :            :         // ignores gatewayData if token already deployed
+     256                 :            : 
+     257                 :            :         {
+     258                 :            :             // validate if L1 address supplied matches that of the expected L2 address
+     259                 :          0 :             (bool success, bytes memory _l1AddressData) = expectedAddress.staticcall(
+     260                 :            :                 abi.encodeWithSelector(IArbToken.l1Address.selector)
+     261                 :            :             );
+     262                 :            : 
+     263                 :          0 :             bool shouldWithdraw;
+     264         [ #  # ]:          0 :             if (!success || _l1AddressData.length < 32) {
+     265                 :          0 :                 shouldWithdraw = true;
+     266                 :            :             } else {
+     267                 :            :                 // we do this in the else branch since we want to avoid reverts
+     268                 :            :                 // and `toAddress` reverts if _l1AddressData has a short length
+     269                 :            :                 // `_l1AddressData` should be 12 bytes of padding then 20 bytes for the address
+     270                 :          0 :                 address expectedL1Address = BytesLib.toAddress(_l1AddressData, 12);
+     271         [ #  # ]:          0 :                 if (expectedL1Address != _token) {
+     272                 :          0 :                     shouldWithdraw = true;
+     273                 :            :                 }
+     274                 :            :             }
+     275                 :            : 
+     276         [ #  # ]:          0 :             if (shouldWithdraw) {
+     277                 :            :                 // we don't need the return value from triggerWithdrawal since this is forcing
+     278                 :            :                 // a withdrawal back to the L1 instead of composing with a L2 dapp
+     279                 :          0 :                 triggerWithdrawal(_token, address(this), _from, _amount, "");
+     280                 :          0 :                 return;
+     281                 :            :             }
+     282                 :            :         }
+     283                 :            : 
+     284                 :          0 :         inboundEscrowTransfer(expectedAddress, _to, _amount);
+     285                 :          0 :         emit DepositFinalized(_token, _from, _to, _amount);
+     286                 :            : 
+     287                 :          0 :         return;
+     288                 :            :     }
+     289                 :            : 
+     290                 :            :     // returns if function should halt after
+     291                 :            :     function handleNoContract(
+     292                 :            :         address _l1Token,
+     293                 :            :         address expectedL2Address,
+     294                 :            :         address _from,
+     295                 :            :         address _to,
+     296                 :            :         uint256 _amount,
+     297                 :            :         bytes memory gatewayData
+     298                 :            :     ) internal virtual returns (bool shouldHalt);
+     299                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2CustomGateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2CustomGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..00771b24f5 --- /dev/null +++ b/coverage/arbitrum/gateway/L2CustomGateway.sol.func-sort-c.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2CustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2CustomGateway.calculateL2TokenAddress0
L2CustomGateway.handleNoContract0
L2CustomGateway.initialize0
L2CustomGateway.registerTokenFromL10
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2CustomGateway.sol.func.html b/coverage/arbitrum/gateway/L2CustomGateway.sol.func.html new file mode 100644 index 0000000000..7f67274113 --- /dev/null +++ b/coverage/arbitrum/gateway/L2CustomGateway.sol.func.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2CustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2CustomGateway.calculateL2TokenAddress0
L2CustomGateway.handleNoContract0
L2CustomGateway.initialize0
L2CustomGateway.registerTokenFromL10
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2CustomGateway.sol.gcov.html b/coverage/arbitrum/gateway/L2CustomGateway.sol.gcov.html new file mode 100644 index 0000000000..67e20c44c9 --- /dev/null +++ b/coverage/arbitrum/gateway/L2CustomGateway.sol.gcov.html @@ -0,0 +1,160 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2CustomGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./L2ArbitrumGateway.sol";
+      22                 :            : import "../../libraries/gateway/ICustomGateway.sol";
+      23                 :            : import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+      24                 :            : 
+      25                 :            : contract L2CustomGateway is L2ArbitrumGateway, ICustomGateway {
+      26                 :            :     // stores addresses of L2 tokens to be used
+      27                 :            :     mapping(address => address) public override l1ToL2Token;
+      28                 :            : 
+      29                 :            :     function initialize(address _l1Counterpart, address _router) public {
+      30                 :          0 :         L2ArbitrumGateway._initialize(_l1Counterpart, _router);
+      31                 :            :     }
+      32                 :            : 
+      33                 :            :     /**
+      34                 :            :      * @notice internal utility function used to handle when no contract is deployed at expected address
+      35                 :            :      */
+      36                 :            :     function handleNoContract(
+      37                 :            :         address _l1Token,
+      38                 :            :         address, /* expectedL2Address */
+      39                 :            :         address _from,
+      40                 :            :         address, /* _to */
+      41                 :            :         uint256 _amount,
+      42                 :            :         bytes memory /* gatewayData */
+      43                 :            :     ) internal override returns (bool shouldHalt) {
+      44                 :            :         // it is assumed that the custom token is deployed in the L2 before deposits are made
+      45                 :            :         // trigger withdrawal
+      46                 :            :         // we don't need the return value from triggerWithdrawal since this is forcing a withdrawal back to the L1
+      47                 :            :         // instead of composing with a L2 dapp
+      48                 :          0 :         triggerWithdrawal(_l1Token, address(this), _from, _amount, "");
+      49                 :          0 :         return true;
+      50                 :            :     }
+      51                 :            : 
+      52                 :            :     /**
+      53                 :            :      * @notice Calculate the address used when bridging an ERC20 token
+      54                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
+      55                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
+      56                 :            :      * @param l1ERC20 address of L1 token
+      57                 :            :      * @return L2 address of a bridged ERC20 token
+      58                 :            :      */
+      59                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override returns (address) {
+      60                 :          0 :         return l1ToL2Token[l1ERC20];
+      61                 :            :     }
+      62                 :            : 
+      63                 :            :     function registerTokenFromL1(address[] calldata l1Address, address[] calldata l2Address)
+      64                 :            :         external
+      65                 :            :         onlyCounterpartGateway
+      66                 :            :     {
+      67                 :            :         // we assume both arrays are the same length, safe since its encoded by the L1
+      68                 :          0 :         for (uint256 i = 0; i < l1Address.length; i++) {
+      69                 :            :             // here we don't check if l2Address is a contract and instead deal with that behaviour
+      70                 :            :             // in `handleNoContract` this way we keep the l1 and l2 address oracles in sync
+      71                 :          0 :             l1ToL2Token[l1Address[i]] = l2Address[i];
+      72                 :          0 :             emit TokenSet(l1Address[i], l2Address[i]);
+      73                 :            :         }
+      74                 :            :     }
+      75                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func-sort-c.html new file mode 100644 index 0000000000..3b38504879 --- /dev/null +++ b/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func-sort-c.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2ERC20Gateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0130.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2ERC20Gateway.calculateL2TokenAddress0
L2ERC20Gateway.cloneableProxyHash0
L2ERC20Gateway.getUserSalt0
L2ERC20Gateway.handleNoContract0
L2ERC20Gateway.initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func.html b/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func.html new file mode 100644 index 0000000000..c6bdd67336 --- /dev/null +++ b/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2ERC20Gateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0130.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2ERC20Gateway.calculateL2TokenAddress0
L2ERC20Gateway.cloneableProxyHash0
L2ERC20Gateway.getUserSalt0
L2ERC20Gateway.handleNoContract0
L2ERC20Gateway.initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2ERC20Gateway.sol.gcov.html b/coverage/arbitrum/gateway/L2ERC20Gateway.sol.gcov.html new file mode 100644 index 0000000000..9921d03c9b --- /dev/null +++ b/coverage/arbitrum/gateway/L2ERC20Gateway.sol.gcov.html @@ -0,0 +1,186 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2ERC20Gateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0130.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:040.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
+      22                 :            : import "@openzeppelin/contracts/utils/Create2.sol";
+      23                 :            : import "./L2ArbitrumGateway.sol";
+      24                 :            : import "../StandardArbERC20.sol";
+      25                 :            : import "../../libraries/ClonableBeaconProxy.sol";
+      26                 :            : 
+      27                 :            : contract L2ERC20Gateway is L2ArbitrumGateway {
+      28                 :            :     address public beaconProxyFactory;
+      29                 :            : 
+      30                 :            :     function initialize(
+      31                 :            :         address _l1Counterpart,
+      32                 :            :         address _router,
+      33                 :            :         address _beaconProxyFactory
+      34                 :            :     ) public {
+      35                 :          0 :         L2ArbitrumGateway._initialize(_l1Counterpart, _router);
+      36         [ #  # ]:          0 :         require(_beaconProxyFactory != address(0), "INVALID_BEACON");
+      37                 :          0 :         beaconProxyFactory = _beaconProxyFactory;
+      38                 :            :     }
+      39                 :            : 
+      40                 :            :     /**
+      41                 :            :      * @notice Calculate the address used when bridging an ERC20 token
+      42                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
+      43                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
+      44                 :            :      * @param l1ERC20 address of L1 token
+      45                 :            :      * @return L2 address of a bridged ERC20 token
+      46                 :            :      */
+      47                 :            :     function calculateL2TokenAddress(address l1ERC20)
+      48                 :            :         public
+      49                 :            :         view
+      50                 :            :         virtual
+      51                 :            :         override
+      52                 :            :         returns (address)
+      53                 :            :     {
+      54                 :            :         // this method is marked virtual to be overriden in subclasses used in testing
+      55                 :          0 :         return
+      56                 :            :             BeaconProxyFactory(beaconProxyFactory).calculateExpectedAddress(
+      57                 :            :                 address(this),
+      58                 :            :                 getUserSalt(l1ERC20)
+      59                 :            :             );
+      60                 :            :     }
+      61                 :            : 
+      62                 :            :     function cloneableProxyHash() public view returns (bytes32) {
+      63                 :          0 :         return BeaconProxyFactory(beaconProxyFactory).cloneableProxyHash();
+      64                 :            :     }
+      65                 :            : 
+      66                 :            :     function getUserSalt(address l1ERC20) public pure returns (bytes32) {
+      67                 :          0 :         return keccak256(abi.encode(l1ERC20));
+      68                 :            :     }
+      69                 :            : 
+      70                 :            :     /**
+      71                 :            :      * @notice internal utility function used to deploy ERC20 tokens with the beacon proxy pattern.
+      72                 :            :      * @dev the transparent proxy implementation by OpenZeppelin can't be used if we want to be able to
+      73                 :            :      * upgrade the token logic.
+      74                 :            :      * @param l1ERC20 L1 address of ERC20
+      75                 :            :      * @param expectedL2Address L2 address of ERC20
+      76                 :            :      * @param deployData encoded symbol/name/decimal data for initial deploy
+      77                 :            :      */
+      78                 :            :     function handleNoContract(
+      79                 :            :         address l1ERC20,
+      80                 :            :         address expectedL2Address,
+      81                 :            :         address _from,
+      82                 :            :         address, /* _to */
+      83                 :            :         uint256 _amount,
+      84                 :            :         bytes memory deployData
+      85                 :            :     ) internal override returns (bool shouldHalt) {
+      86                 :          0 :         bytes32 userSalt = getUserSalt(l1ERC20);
+      87                 :          0 :         address createdContract = BeaconProxyFactory(beaconProxyFactory).createProxy(userSalt);
+      88                 :            : 
+      89                 :          0 :         StandardArbERC20(createdContract).bridgeInit(l1ERC20, deployData);
+      90                 :            : 
+      91         [ #  # ]:          0 :         if (createdContract == expectedL2Address) {
+      92                 :          0 :             return false;
+      93                 :            :         } else {
+      94                 :            :             // trigger withdrawal then halt
+      95                 :            :             // this codepath should only be hit if the system is setup incorrectly
+      96                 :            :             // this withdrawal is for error recovery, not composing with L2 dapps, so we ignore the return value
+      97                 :          0 :             triggerWithdrawal(l1ERC20, address(this), _from, _amount, "");
+      98                 :          0 :             return true;
+      99                 :            :         }
+     100                 :            :     }
+     101                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2GatewayRouter.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2GatewayRouter.sol.func-sort-c.html new file mode 100644 index 0000000000..448b12e8be --- /dev/null +++ b/coverage/arbitrum/gateway/L2GatewayRouter.sol.func-sort-c.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2GatewayRouter.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:080.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2GatewayRouter.initialize0
L2GatewayRouter.outboundTransfer0
L2GatewayRouter.setDefaultGateway0
L2GatewayRouter.setGateway0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2GatewayRouter.sol.func.html b/coverage/arbitrum/gateway/L2GatewayRouter.sol.func.html new file mode 100644 index 0000000000..2174662732 --- /dev/null +++ b/coverage/arbitrum/gateway/L2GatewayRouter.sol.func.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2GatewayRouter.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:080.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2GatewayRouter.initialize0
L2GatewayRouter.outboundTransfer0
L2GatewayRouter.setDefaultGateway0
L2GatewayRouter.setGateway0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2GatewayRouter.sol.gcov.html b/coverage/arbitrum/gateway/L2GatewayRouter.sol.gcov.html new file mode 100644 index 0000000000..29af200b61 --- /dev/null +++ b/coverage/arbitrum/gateway/L2GatewayRouter.sol.gcov.html @@ -0,0 +1,154 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2GatewayRouter.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:080.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:020.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../../libraries/gateway/GatewayRouter.sol";
+      22                 :            : import "../../ethereum/gateway/L1GatewayRouter.sol";
+      23                 :            : import "../L2ArbitrumMessenger.sol";
+      24                 :            : import "../../libraries/AddressAliasHelper.sol";
+      25                 :            : 
+      26                 :            : /**
+      27                 :            :  * @title Handles withdrawals from Ethereum into Arbitrum. Tokens are routered to their appropriate L2 gateway (Router itself also conforms to the Gateway interface).
+      28                 :            :  * @notice Router also serves as an L2-L1 token address oracle.
+      29                 :            :  */
+      30                 :            : contract L2GatewayRouter is GatewayRouter, L2ArbitrumMessenger {
+      31                 :            :     modifier onlyCounterpartGateway() override {
+      32                 :            :         require(
+      33                 :            :             msg.sender == AddressAliasHelper.applyL1ToL2Alias(counterpartGateway),
+      34                 :            :             "ONLY_COUNTERPART_GATEWAY"
+      35                 :            :         );
+      36                 :            :         _;
+      37                 :            :     }
+      38                 :            : 
+      39                 :            :     function initialize(address _counterpartGateway, address _defaultGateway) public {
+      40                 :          0 :         GatewayRouter._initialize(_counterpartGateway, address(0), _defaultGateway);
+      41                 :            :     }
+      42                 :            : 
+      43                 :            :     function setGateway(address[] memory _l1Token, address[] memory _gateway)
+      44                 :            :         external
+      45                 :            :         onlyCounterpartGateway
+      46                 :            :     {
+      47                 :            :         // counterpart gateway (L1 router) should never allow wrong lengths
+      48         [ #  # ]:          0 :         assert(_l1Token.length == _gateway.length);
+      49                 :            : 
+      50                 :          0 :         for (uint256 i = 0; i < _l1Token.length; i++) {
+      51                 :          0 :             l1TokenToGateway[_l1Token[i]] = _gateway[i];
+      52                 :          0 :             emit GatewaySet(_l1Token[i], _gateway[i]);
+      53                 :            :         }
+      54                 :            :     }
+      55                 :            : 
+      56                 :            :     function outboundTransfer(
+      57                 :            :         address _l1Token,
+      58                 :            :         address _to,
+      59                 :            :         uint256 _amount,
+      60                 :            :         bytes calldata _data
+      61                 :            :     ) public payable returns (bytes memory) {
+      62                 :          0 :         return outboundTransfer(_l1Token, _to, _amount, 0, 0, _data);
+      63                 :            :     }
+      64                 :            : 
+      65                 :            :     function setDefaultGateway(address newL2DefaultGateway) external onlyCounterpartGateway {
+      66                 :          0 :         defaultGateway = newL2DefaultGateway;
+      67                 :          0 :         emit DefaultGatewayUpdated(newL2DefaultGateway);
+      68                 :            :     }
+      69                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..abcd02a31b --- /dev/null +++ b/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2ReverseCustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:050.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2ReverseCustomGateway.inboundEscrowTransfer0
L2ReverseCustomGateway.outboundEscrowTransfer0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func.html b/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func.html new file mode 100644 index 0000000000..ddf52efc9d --- /dev/null +++ b/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2ReverseCustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:050.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2ReverseCustomGateway.inboundEscrowTransfer0
L2ReverseCustomGateway.outboundEscrowTransfer0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.gcov.html b/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.gcov.html new file mode 100644 index 0000000000..19078f2953 --- /dev/null +++ b/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.gcov.html @@ -0,0 +1,146 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2ReverseCustomGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:050.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./L2CustomGateway.sol";
+      22                 :            : import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
+      23                 :            : 
+      24                 :            : /**
+      25                 :            :  * @title   L2 Gateway for reverse "custom" bridging functionality
+      26                 :            :  * @notice  Handles some (but not all!) reverse custom Gateway needs.
+      27                 :            :  *          Use the reverse custom gateway instead of the normal custom
+      28                 :            :  *          gateway if you want total supply to be tracked on the L2
+      29                 :            :  *          rather than the L1.
+      30                 :            :  * @dev     The reverse custom gateway burns on the l2 and escrows on the l1
+      31                 :            :  *          which is the opposite of the way the normal custom gateway works
+      32                 :            :  *          This means that the total supply L2 isn't affected by briding, which
+      33                 :            :  *          is helpful for obeservers calculating the total supply especially if
+      34                 :            :  *          if minting is also occuring on L2
+      35                 :            :  */
+      36                 :            : contract L2ReverseCustomGateway is L2CustomGateway {
+      37                 :            :     using SafeERC20 for IERC20;
+      38                 :            : 
+      39                 :            :     function inboundEscrowTransfer(
+      40                 :            :         address _l2Token,
+      41                 :            :         address _dest,
+      42                 :            :         uint256 _amount
+      43                 :            :     ) internal virtual override {
+      44                 :          0 :         IERC20(_l2Token).safeTransfer(_dest, _amount);
+      45                 :            :     }
+      46                 :            : 
+      47                 :            :     function outboundEscrowTransfer(
+      48                 :            :         address _l2Token,
+      49                 :            :         address _from,
+      50                 :            :         uint256 _amount
+      51                 :            :     ) internal override returns (uint256) {
+      52                 :          0 :         uint256 prevBalance = IERC20(_l2Token).balanceOf(address(this));
+      53                 :            :         // as in the normal custom gateway, in the reverse custom gateway we check
+      54                 :            :         // for the balances of tokens to ensure that inflationary / deflationary changes in the amount
+      55                 :            :         // are taken into account we ignore the return value since we actually query the token before
+      56                 :            :         // and after to calculate the amount of tokens that were transferred
+      57                 :          0 :         IERC20(_l2Token).safeTransferFrom(_from, address(this), _amount);
+      58                 :          0 :         uint256 postBalance = IERC20(_l2Token).balanceOf(address(this));
+      59                 :          0 :         return postBalance - prevBalance;
+      60                 :            :     }
+      61                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2WethGateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2WethGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..67b6692cd5 --- /dev/null +++ b/coverage/arbitrum/gateway/L2WethGateway.sol.func-sort-c.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2WethGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2WethGateway.calculateL2TokenAddress0
L2WethGateway.createOutboundTx0
L2WethGateway.handleNoContract0
L2WethGateway.inboundEscrowTransfer0
L2WethGateway.initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2WethGateway.sol.func.html b/coverage/arbitrum/gateway/L2WethGateway.sol.func.html new file mode 100644 index 0000000000..b031cb0c4d --- /dev/null +++ b/coverage/arbitrum/gateway/L2WethGateway.sol.func.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2WethGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2WethGateway.calculateL2TokenAddress0
L2WethGateway.createOutboundTx0
L2WethGateway.handleNoContract0
L2WethGateway.inboundEscrowTransfer0
L2WethGateway.initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/L2WethGateway.sol.gcov.html b/coverage/arbitrum/gateway/L2WethGateway.sol.gcov.html new file mode 100644 index 0000000000..51e1459e61 --- /dev/null +++ b/coverage/arbitrum/gateway/L2WethGateway.sol.gcov.html @@ -0,0 +1,192 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway/L2WethGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gateway - L2WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:060.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./L2ArbitrumGateway.sol";
+      22                 :            : import "../../libraries/IWETH9.sol";
+      23                 :            : import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+      24                 :            : import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
+      25                 :            : 
+      26                 :            : contract L2WethGateway is L2ArbitrumGateway {
+      27                 :            :     using SafeERC20 for IERC20;
+      28                 :            : 
+      29                 :            :     address public l1Weth;
+      30                 :            :     address public l2Weth;
+      31                 :            : 
+      32                 :            :     function initialize(
+      33                 :            :         address _l1Counterpart,
+      34                 :            :         address _router,
+      35                 :            :         address _l1Weth,
+      36                 :            :         address _l2Weth
+      37                 :            :     ) public {
+      38                 :          0 :         L2ArbitrumGateway._initialize(_l1Counterpart, _router);
+      39         [ #  # ]:          0 :         require(_l1Weth != address(0), "INVALID_L1WETH");
+      40         [ #  # ]:          0 :         require(_l2Weth != address(0), "INVALID_L2WETH");
+      41                 :          0 :         l1Weth = _l1Weth;
+      42                 :          0 :         l2Weth = _l2Weth;
+      43                 :            :     }
+      44                 :            : 
+      45                 :            :     /**
+      46                 :            :      * @notice internal utility function used to handle when no contract is deployed at expected address
+      47                 :            :      * @param l1ERC20 L1 address of ERC20
+      48                 :            :      */
+      49                 :            :     function handleNoContract(
+      50                 :            :         address l1ERC20,
+      51                 :            :         address, /* expectedL2Address */
+      52                 :            :         address _from,
+      53                 :            :         address, /* _to */
+      54                 :            :         uint256 _amount,
+      55                 :            :         bytes memory /* deployData */
+      56                 :            :     ) internal override returns (bool shouldHalt) {
+      57                 :            :         // it is assumed that the custom token is deployed in the L2 before deposits are made
+      58                 :            :         // trigger withdrawal
+      59                 :            :         // this codepath should only be hit if the system is setup incorrectly
+      60                 :            :         // this withdrawal is for error recovery, not composing with L2 dapps, so we ignore the return value
+      61                 :          0 :         triggerWithdrawal(l1ERC20, address(this), _from, _amount, "");
+      62                 :          0 :         return true;
+      63                 :            :     }
+      64                 :            : 
+      65                 :            :     /**
+      66                 :            :      * @notice Calculate the address used when bridging an ERC20 token
+      67                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
+      68                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
+      69                 :            :      * @param l1ERC20 address of L1 token
+      70                 :            :      * @return L2 address of a bridged ERC20 token
+      71                 :            :      */
+      72                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override returns (address) {
+      73         [ #  # ]:          0 :         if (l1ERC20 != l1Weth) {
+      74                 :            :             // invalid L1 weth address
+      75                 :          0 :             return address(0);
+      76                 :            :         }
+      77                 :          0 :         return l2Weth;
+      78                 :            :     }
+      79                 :            : 
+      80                 :            :     function inboundEscrowTransfer(
+      81                 :            :         address _l2TokenAddress,
+      82                 :            :         address _dest,
+      83                 :            :         uint256 _amount
+      84                 :            :     ) internal override {
+      85                 :          0 :         IWETH9(_l2TokenAddress).deposit{ value: _amount }();
+      86                 :          0 :         IERC20(_l2TokenAddress).safeTransfer(_dest, _amount);
+      87                 :            :     }
+      88                 :            : 
+      89                 :            :     function createOutboundTx(
+      90                 :            :         address _from,
+      91                 :            :         uint256 _tokenAmount,
+      92                 :            :         bytes memory _outboundCalldata
+      93                 :            :     ) internal override returns (uint256) {
+      94                 :            :         // exitNum incremented after being included in _outboundCalldata
+      95                 :          0 :         exitNum++;
+      96                 :          0 :         return
+      97                 :            :             sendTxToL1(
+      98                 :            :                 // we send the amount of weth withdrawn as callvalue to the L1 gateway
+      99                 :            :                 _tokenAmount,
+     100                 :            :                 _from,
+     101                 :            :                 counterpartGateway,
+     102                 :            :                 _outboundCalldata
+     103                 :            :             );
+     104                 :            :     }
+     105                 :            : 
+     106                 :            :     receive() external payable {}
+     107                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/index-sort-b.html b/coverage/arbitrum/gateway/index-sort-b.html new file mode 100644 index 0000000000..5c31eef1d9 --- /dev/null +++ b/coverage/arbitrum/gateway/index-sort-b.html @@ -0,0 +1,167 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gatewayHitTotalCoverage
Test:lcov.infoLines:0980.0 %
Date:2023-04-27 16:26:32Functions:0290.0 %
Branches:0380.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2GatewayRouter.sol +
0.0%
+
0.0 %0 / 80.0 %0 / 40.0 %0 / 2
L2ERC20Gateway.sol +
0.0%
+
0.0 %0 / 130.0 %0 / 50.0 %0 / 4
L2WethGateway.sol +
0.0%
+
0.0 %0 / 140.0 %0 / 50.0 %0 / 6
L2ArbitrumGateway.sol +
0.0%
+
0.0 %0 / 510.0 %0 / 90.0 %0 / 26
L2CustomGateway.sol +
0.0%
+
0.0 %0 / 70.0 %0 / 4-0 / 0
L2ReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 50.0 %0 / 2-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/index-sort-f.html b/coverage/arbitrum/gateway/index-sort-f.html new file mode 100644 index 0000000000..1370b54700 --- /dev/null +++ b/coverage/arbitrum/gateway/index-sort-f.html @@ -0,0 +1,167 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gatewayHitTotalCoverage
Test:lcov.infoLines:0980.0 %
Date:2023-04-27 16:26:32Functions:0290.0 %
Branches:0380.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 50.0 %0 / 2-0 / 0
L2GatewayRouter.sol +
0.0%
+
0.0 %0 / 80.0 %0 / 40.0 %0 / 2
L2CustomGateway.sol +
0.0%
+
0.0 %0 / 70.0 %0 / 4-0 / 0
L2ERC20Gateway.sol +
0.0%
+
0.0 %0 / 130.0 %0 / 50.0 %0 / 4
L2WethGateway.sol +
0.0%
+
0.0 %0 / 140.0 %0 / 50.0 %0 / 6
L2ArbitrumGateway.sol +
0.0%
+
0.0 %0 / 510.0 %0 / 90.0 %0 / 26
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/index-sort-l.html b/coverage/arbitrum/gateway/index-sort-l.html new file mode 100644 index 0000000000..10db529782 --- /dev/null +++ b/coverage/arbitrum/gateway/index-sort-l.html @@ -0,0 +1,167 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gatewayHitTotalCoverage
Test:lcov.infoLines:0980.0 %
Date:2023-04-27 16:26:32Functions:0290.0 %
Branches:0380.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 50.0 %0 / 2-0 / 0
L2CustomGateway.sol +
0.0%
+
0.0 %0 / 70.0 %0 / 4-0 / 0
L2GatewayRouter.sol +
0.0%
+
0.0 %0 / 80.0 %0 / 40.0 %0 / 2
L2ERC20Gateway.sol +
0.0%
+
0.0 %0 / 130.0 %0 / 50.0 %0 / 4
L2WethGateway.sol +
0.0%
+
0.0 %0 / 140.0 %0 / 50.0 %0 / 6
L2ArbitrumGateway.sol +
0.0%
+
0.0 %0 / 510.0 %0 / 90.0 %0 / 26
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/gateway/index.html b/coverage/arbitrum/gateway/index.html new file mode 100644 index 0000000000..2f8d88b1ce --- /dev/null +++ b/coverage/arbitrum/gateway/index.html @@ -0,0 +1,167 @@ + + + + + + + LCOV - lcov.info - arbitrum/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrum/gatewayHitTotalCoverage
Test:lcov.infoLines:0980.0 %
Date:2023-04-27 16:26:32Functions:0290.0 %
Branches:0380.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ArbitrumGateway.sol +
0.0%
+
0.0 %0 / 510.0 %0 / 90.0 %0 / 26
L2CustomGateway.sol +
0.0%
+
0.0 %0 / 70.0 %0 / 4-0 / 0
L2ERC20Gateway.sol +
0.0%
+
0.0 %0 / 130.0 %0 / 50.0 %0 / 4
L2GatewayRouter.sol +
0.0%
+
0.0 %0 / 80.0 %0 / 40.0 %0 / 2
L2ReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 50.0 %0 / 2-0 / 0
L2WethGateway.sol +
0.0%
+
0.0 %0 / 140.0 %0 / 50.0 %0 / 6
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/index-sort-b.html b/coverage/arbitrum/index-sort-b.html new file mode 100644 index 0000000000..276e3696f8 --- /dev/null +++ b/coverage/arbitrum/index-sort-b.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - arbitrum + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrumHitTotalCoverage
Test:lcov.infoLines:0170.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
StandardArbERC20.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 40.0 %0 / 6
L2ArbitrumMessenger.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 1-0 / 0
ReverseArbToken.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/index-sort-f.html b/coverage/arbitrum/index-sort-f.html new file mode 100644 index 0000000000..c747ddb47a --- /dev/null +++ b/coverage/arbitrum/index-sort-f.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - arbitrum + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrumHitTotalCoverage
Test:lcov.infoLines:0170.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ArbitrumMessenger.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 1-0 / 0
ReverseArbToken.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
StandardArbERC20.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 40.0 %0 / 6
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/index-sort-l.html b/coverage/arbitrum/index-sort-l.html new file mode 100644 index 0000000000..9388bebc75 --- /dev/null +++ b/coverage/arbitrum/index-sort-l.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - arbitrum + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrumHitTotalCoverage
Test:lcov.infoLines:0170.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
ReverseArbToken.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
L2ArbitrumMessenger.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 1-0 / 0
StandardArbERC20.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 40.0 %0 / 6
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/arbitrum/index.html b/coverage/arbitrum/index.html new file mode 100644 index 0000000000..d5fd659753 --- /dev/null +++ b/coverage/arbitrum/index.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - arbitrum + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - arbitrumHitTotalCoverage
Test:lcov.infoLines:0170.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ArbitrumMessenger.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 1-0 / 0
ReverseArbToken.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
StandardArbERC20.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 40.0 %0 / 6
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/emerald.png b/coverage/emerald.png new file mode 100644 index 0000000000000000000000000000000000000000..38ad4f4068b935643d2486f323005fb294a9bd7e GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^Jb!lvI6;R0X`wF(yt=9xVZRt1vCRixIA4P dLn>}1Cji+@42)0J?}79&c)I$ztaD0e0sy@GAL0N2 literal 0 HcmV?d00001 diff --git a/coverage/ethereum/L1ArbitrumMessenger.sol.func-sort-c.html b/coverage/ethereum/L1ArbitrumMessenger.sol.func-sort-c.html new file mode 100644 index 0000000000..e59cc4d84e --- /dev/null +++ b/coverage/ethereum/L1ArbitrumMessenger.sol.func-sort-c.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - ethereum/L1ArbitrumMessenger.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum - L1ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumMessenger.getL2ToL1Sender4
L1ArbitrumMessenger.getBridge10
L1ArbitrumMessenger._createRetryable15
L1ArbitrumMessenger.sendTxToL220
L1ArbitrumMessenger.sendTxToL2CustomRefund21
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/L1ArbitrumMessenger.sol.func.html b/coverage/ethereum/L1ArbitrumMessenger.sol.func.html new file mode 100644 index 0000000000..6ab5f1e884 --- /dev/null +++ b/coverage/ethereum/L1ArbitrumMessenger.sol.func.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - ethereum/L1ArbitrumMessenger.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum - L1ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumMessenger._createRetryable15
L1ArbitrumMessenger.getBridge10
L1ArbitrumMessenger.getL2ToL1Sender4
L1ArbitrumMessenger.sendTxToL220
L1ArbitrumMessenger.sendTxToL2CustomRefund21
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/L1ArbitrumMessenger.sol.gcov.html b/coverage/ethereum/L1ArbitrumMessenger.sol.gcov.html new file mode 100644 index 0000000000..740132cfbd --- /dev/null +++ b/coverage/ethereum/L1ArbitrumMessenger.sol.gcov.html @@ -0,0 +1,302 @@ + + + + + + + LCOV - lcov.info - ethereum/L1ArbitrumMessenger.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum - L1ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "@arbitrum/nitro-contracts/src/bridge/IInbox.sol";
+      22                 :            : import "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol";
+      23                 :            : 
+      24                 :            : /// @notice L1 utility contract to assist with L1 <=> L2 interactions
+      25                 :            : /// @dev this is an abstract contract instead of library so the functions can be easily overriden when testing
+      26                 :            : abstract contract L1ArbitrumMessenger {
+      27                 :            :     event TxToL2(address indexed _from, address indexed _to, uint256 indexed _seqNum, bytes _data);
+      28                 :            : 
+      29                 :            :     struct L2GasParams {
+      30                 :            :         uint256 _maxSubmissionCost;
+      31                 :            :         uint256 _maxGas;
+      32                 :            :         uint256 _gasPriceBid;
+      33                 :            :     }
+      34                 :            : 
+      35                 :            :     function sendTxToL2CustomRefund(
+      36                 :            :         address _inbox,
+      37                 :            :         address _to,
+      38                 :            :         address _refundTo,
+      39                 :            :         address _user,
+      40                 :            :         uint256 _l1CallValue,
+      41                 :            :         uint256 _l2CallValue,
+      42                 :            :         L2GasParams memory _l2GasParams,
+      43                 :            :         bytes memory _data
+      44                 :            :     ) internal returns (uint256) {
+      45                 :            :         // alternative function entry point when struggling with the stack size
+      46                 :          4 :         return
+      47                 :            :             sendTxToL2CustomRefund(
+      48                 :            :                 _inbox,
+      49                 :            :                 _to,
+      50                 :            :                 _refundTo,
+      51                 :            :                 _user,
+      52                 :            :                 _l1CallValue,
+      53                 :            :                 _l2CallValue,
+      54                 :            :                 _l2GasParams._maxSubmissionCost,
+      55                 :            :                 _l2GasParams._maxGas,
+      56                 :            :                 _l2GasParams._gasPriceBid,
+      57                 :            :                 _data
+      58                 :            :             );
+      59                 :            :     }
+      60                 :            : 
+      61                 :            :     function sendTxToL2(
+      62                 :            :         address _inbox,
+      63                 :            :         address _to,
+      64                 :            :         address _user,
+      65                 :            :         uint256 _l1CallValue,
+      66                 :            :         uint256 _l2CallValue,
+      67                 :            :         L2GasParams memory _l2GasParams,
+      68                 :            :         bytes memory _data
+      69                 :            :     ) internal returns (uint256) {
+      70                 :            :         // alternative function entry point when struggling with the stack size
+      71                 :          7 :         return
+      72                 :            :             sendTxToL2(
+      73                 :            :                 _inbox,
+      74                 :            :                 _to,
+      75                 :            :                 _user,
+      76                 :            :                 _l1CallValue,
+      77                 :            :                 _l2CallValue,
+      78                 :            :                 _l2GasParams._maxSubmissionCost,
+      79                 :            :                 _l2GasParams._maxGas,
+      80                 :            :                 _l2GasParams._gasPriceBid,
+      81                 :            :                 _data
+      82                 :            :             );
+      83                 :            :     }
+      84                 :            : 
+      85                 :            :     function sendTxToL2CustomRefund(
+      86                 :            :         address _inbox,
+      87                 :            :         address _to,
+      88                 :            :         address _refundTo,
+      89                 :            :         address _user,
+      90                 :            :         uint256 _l1CallValue,
+      91                 :            :         uint256 _l2CallValue,
+      92                 :            :         uint256 _maxSubmissionCost,
+      93                 :            :         uint256 _maxGas,
+      94                 :            :         uint256 _gasPriceBid,
+      95                 :            :         bytes memory _data
+      96                 :            :     ) internal returns (uint256) {
+      97                 :         17 :         uint256 seqNum = _createRetryable(
+      98                 :            :             _inbox,
+      99                 :            :             _to,
+     100                 :            :             _refundTo,
+     101                 :            :             _user,
+     102                 :            :             _l1CallValue,
+     103                 :            :             _l2CallValue,
+     104                 :            :             _maxSubmissionCost,
+     105                 :            :             _maxGas,
+     106                 :            :             _gasPriceBid,
+     107                 :            :             _data
+     108                 :            :         );
+     109                 :         17 :         emit TxToL2(_user, _to, seqNum, _data);
+     110                 :         17 :         return seqNum;
+     111                 :            :     }
+     112                 :            : 
+     113                 :            :     function sendTxToL2(
+     114                 :            :         address _inbox,
+     115                 :            :         address _to,
+     116                 :            :         address _user,
+     117                 :            :         uint256 _l1CallValue,
+     118                 :            :         uint256 _l2CallValue,
+     119                 :            :         uint256 _maxSubmissionCost,
+     120                 :            :         uint256 _maxGas,
+     121                 :            :         uint256 _gasPriceBid,
+     122                 :            :         bytes memory _data
+     123                 :            :     ) internal returns (uint256) {
+     124                 :         13 :         return
+     125                 :            :             sendTxToL2CustomRefund(
+     126                 :            :                 _inbox,
+     127                 :            :                 _to,
+     128                 :            :                 _user,
+     129                 :            :                 _user,
+     130                 :            :                 _l1CallValue,
+     131                 :            :                 _l2CallValue,
+     132                 :            :                 _maxSubmissionCost,
+     133                 :            :                 _maxGas,
+     134                 :            :                 _gasPriceBid,
+     135                 :            :                 _data
+     136                 :            :             );
+     137                 :            :     }
+     138                 :            : 
+     139                 :            :     function getBridge(address _inbox) internal view returns (IBridge) {
+     140                 :         10 :         return IInbox(_inbox).bridge();
+     141                 :            :     }
+     142                 :            : 
+     143                 :            :     /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
+     144                 :            :     function getL2ToL1Sender(address _inbox) internal view returns (address) {
+     145                 :          4 :         IOutbox outbox = IOutbox(getBridge(_inbox).activeOutbox());
+     146                 :          4 :         address l2ToL1Sender = outbox.l2ToL1Sender();
+     147                 :            : 
+     148         [ #  + ]:          4 :         require(l2ToL1Sender != address(0), "NO_SENDER");
+     149                 :          4 :         return l2ToL1Sender;
+     150                 :            :     }
+     151                 :            : 
+     152                 :            :     /**
+     153                 :            :      * @notice Calls inbox to create retryable ticket. Default implementation is for standard Eth-based rollup, but it can be overriden to create retryable in ERC20-based rollup.
+     154                 :            :      * @param _inbox address of the rollup's inbox
+     155                 :            :      * @param _to destination L2 contract address
+     156                 :            :      * @param _refundTo refund address for excess fee
+     157                 :            :      * @param _user refund address for callvalue
+     158                 :            :      * @param _totalFeeAmount amount of fees to pay, in Eth or native token, for retryable's execution
+     159                 :            :      * @param _l2CallValue call value for retryable L2 message
+     160                 :            :      * @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
+     161                 :            :      * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution
+     162                 :            :      * @param _gasPriceBid price bid for L2 execution
+     163                 :            :      * @param _data ABI encoded data of L2 message
+     164                 :            :      * @return unique message number of the retryable transaction
+     165                 :            :      */
+     166                 :            :     function _createRetryable(
+     167                 :            :         address _inbox,
+     168                 :            :         address _to,
+     169                 :            :         address _refundTo,
+     170                 :            :         address _user,
+     171                 :            :         uint256 _totalFeeAmount,
+     172                 :            :         uint256 _l2CallValue,
+     173                 :            :         uint256 _maxSubmissionCost,
+     174                 :            :         uint256 _maxGas,
+     175                 :            :         uint256 _gasPriceBid,
+     176                 :            :         bytes memory _data
+     177                 :            :     ) internal virtual returns (uint256) {
+     178                 :         15 :         return
+     179                 :            :             IEthInbox(_inbox).createRetryableTicket{ value: _totalFeeAmount }(
+     180                 :            :                 _to,
+     181                 :            :                 _l2CallValue,
+     182                 :            :                 _maxSubmissionCost,
+     183                 :            :                 _refundTo,
+     184                 :            :                 _user,
+     185                 :            :                 _maxGas,
+     186                 :            :                 _gasPriceBid,
+     187                 :            :                 _data
+     188                 :            :             );
+     189                 :            :     }
+     190                 :            : }
+     191                 :            : 
+     192                 :            : interface IERC20Inbox {
+     193                 :            :     function createRetryableTicket(
+     194                 :            :         address to,
+     195                 :            :         uint256 l2CallValue,
+     196                 :            :         uint256 maxSubmissionCost,
+     197                 :            :         address excessFeeRefundAddress,
+     198                 :            :         address callValueRefundAddress,
+     199                 :            :         uint256 gasLimit,
+     200                 :            :         uint256 maxFeePerGas,
+     201                 :            :         uint256 tokenTotalFeeAmount,
+     202                 :            :         bytes calldata data
+     203                 :            :     ) external returns (uint256);
+     204                 :            : }
+     205                 :            : 
+     206                 :            : interface IEthInbox {
+     207                 :            :     function createRetryableTicket(
+     208                 :            :         address to,
+     209                 :            :         uint256 l2CallValue,
+     210                 :            :         uint256 maxSubmissionCost,
+     211                 :            :         address excessFeeRefundAddress,
+     212                 :            :         address callValueRefundAddress,
+     213                 :            :         uint256 gasLimit,
+     214                 :            :         uint256 maxFeePerGas,
+     215                 :            :         bytes calldata data
+     216                 :            :     ) external payable returns (uint256);
+     217                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..9018b92e80 --- /dev/null +++ b/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func-sort-c.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ArbitrumExtendedGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ArbitrumExtendedGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1717100.0 %
Date:2023-04-27 16:26:32Functions:44100.0 %
Branches:101283.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumExtendedGateway.encodeWithdrawal512
L1ArbitrumExtendedGateway.getExternalCall1024
L1ArbitrumExtendedGateway.setRedirectedExit5632
L1ArbitrumExtendedGateway.transferExitAndCall5636
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func.html b/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func.html new file mode 100644 index 0000000000..172a5e10af --- /dev/null +++ b/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ArbitrumExtendedGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ArbitrumExtendedGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1717100.0 %
Date:2023-04-27 16:26:32Functions:44100.0 %
Branches:101283.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumExtendedGateway.encodeWithdrawal512
L1ArbitrumExtendedGateway.getExternalCall1024
L1ArbitrumExtendedGateway.setRedirectedExit5632
L1ArbitrumExtendedGateway.transferExitAndCall5636
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.gcov.html b/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.gcov.html new file mode 100644 index 0000000000..aeb06de666 --- /dev/null +++ b/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.gcov.html @@ -0,0 +1,223 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ArbitrumExtendedGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ArbitrumExtendedGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1717100.0 %
Date:2023-04-27 16:26:32Functions:44100.0 %
Branches:101283.3 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../../libraries/ITransferAndCall.sol";
+      22                 :            : 
+      23                 :            : import "./L1ArbitrumGateway.sol";
+      24                 :            : 
+      25                 :            : interface ITradeableExitReceiver {
+      26                 :            :     function onExitTransfer(
+      27                 :            :         address sender,
+      28                 :            :         uint256 exitNum,
+      29                 :            :         bytes calldata data
+      30                 :            :     ) external returns (bool);
+      31                 :            : }
+      32                 :            : 
+      33                 :            : abstract contract L1ArbitrumExtendedGateway is L1ArbitrumGateway {
+      34                 :            :     struct ExitData {
+      35                 :            :         bool isExit;
+      36                 :            :         address _newTo;
+      37                 :            :         bytes _newData;
+      38                 :            :     }
+      39                 :            : 
+      40                 :            :     mapping(bytes32 => ExitData) public redirectedExits;
+      41                 :            : 
+      42                 :            :     event WithdrawRedirected(
+      43                 :            :         address indexed from,
+      44                 :            :         address indexed to,
+      45                 :            :         uint256 indexed exitNum,
+      46                 :            :         bytes newData,
+      47                 :            :         bytes data,
+      48                 :            :         bool madeExternalCall
+      49                 :            :     );
+      50                 :            : 
+      51                 :            :     /**
+      52                 :            :      * @notice Allows a user to redirect their right to claim a withdrawal to another address.
+      53                 :            :      * @dev This method also allows you to make an arbitrary call after the transfer.
+      54                 :            :      * This does not validate if the exit was already triggered. It is assumed the `_exitNum` is
+      55                 :            :      * validated off-chain to ensure this was not yet triggered.
+      56                 :            :      * @param _exitNum Sequentially increasing exit counter determined by the L2 bridge
+      57                 :            :      * @param _initialDestination address the L2 withdrawal call initially set as the destination.
+      58                 :            :      * @param _newDestination address the L1 will now call instead of the previously set destination
+      59                 :            :      * @param _newData data to be used in inboundEscrowAndCall
+      60                 :            :      * @param _data optional data for external call upon transfering the exit
+      61                 :            :      */
+      62                 :            :     function transferExitAndCall(
+      63                 :            :         uint256 _exitNum,
+      64                 :            :         address _initialDestination,
+      65                 :            :         address _newDestination,
+      66                 :            :         bytes calldata _newData,
+      67                 :            :         bytes calldata _data
+      68                 :            :     ) external {
+      69                 :            :         // the initial data doesn't make a difference when transfering you exit
+      70                 :            :         // since the L2 bridge gives a unique exit ID to each exit
+      71                 :       5636 :         (address expectedSender, ) = getExternalCall(_exitNum, _initialDestination, "");
+      72                 :            : 
+      73                 :            :         // if you want to transfer your exit, you must be the current destination
+      74         [ +  + ]:       5636 :         require(msg.sender == expectedSender, "NOT_EXPECTED_SENDER");
+      75                 :            :         // the inboundEscrowAndCall functionality has been disabled, so no data is allowed
+      76         [ +  + ]:       5634 :         require(_newData.length == 0, "NO_DATA_ALLOWED");
+      77                 :            : 
+      78                 :       5632 :         setRedirectedExit(_exitNum, _initialDestination, _newDestination, _newData);
+      79                 :            : 
+      80         [ +  + ]:       5632 :         if (_data.length > 0) {
+      81         [ +  + ]:       3584 :             require(Address.isContract(_newDestination), "TO_NOT_CONTRACT");
+      82                 :       3072 :             bool success = ITradeableExitReceiver(_newDestination).onExitTransfer(
+      83                 :            :                 expectedSender,
+      84                 :            :                 _exitNum,
+      85                 :            :                 _data
+      86                 :            :             );
+      87         [ +  + ]:       3072 :             require(success, "TRANSFER_HOOK_FAIL");
+      88                 :            :         }
+      89                 :            : 
+      90                 :       4096 :         emit WithdrawRedirected(
+      91                 :            :             expectedSender,
+      92                 :            :             _newDestination,
+      93                 :            :             _exitNum,
+      94                 :            :             _newData,
+      95                 :            :             _data,
+      96                 :            :             _data.length > 0
+      97                 :            :         );
+      98                 :            :     }
+      99                 :            : 
+     100                 :            :     /// @notice this does not verify if the external call was already done
+     101                 :            :     function getExternalCall(
+     102                 :            :         uint256 _exitNum,
+     103                 :            :         address _initialDestination,
+     104                 :            :         bytes memory _initialData
+     105                 :            :     ) public view virtual override returns (address target, bytes memory data) {
+     106                 :            :         // this function is virtual so that subclasses can override it with custom logic where necessary
+     107                 :       6662 :         bytes32 withdrawData = encodeWithdrawal(_exitNum, _initialDestination);
+     108                 :       6662 :         ExitData storage exit = redirectedExits[withdrawData];
+     109                 :            : 
+     110                 :            :         // here we don't authenticate `_initialData`. we could hash it into `withdrawData` but would increase gas costs
+     111                 :            :         // this is safe because if the exit isn't overriden, the _initialData coming from L2 is trusted
+     112                 :            :         // but if the exit is traded, all we care about is the latest user calldata
+     113         [ #  # ]:       6662 :         if (exit.isExit) {
+     114                 :       2048 :             return (exit._newTo, exit._newData);
+     115                 :            :         } else {
+     116                 :       4614 :             return (_initialDestination, _initialData);
+     117                 :            :         }
+     118                 :            :     }
+     119                 :            : 
+     120                 :            :     function setRedirectedExit(
+     121                 :            :         uint256 _exitNum,
+     122                 :            :         address _initialDestination,
+     123                 :            :         address _newDestination,
+     124                 :            :         bytes memory _newData
+     125                 :            :     ) internal virtual {
+     126                 :       5632 :         bytes32 withdrawData = encodeWithdrawal(_exitNum, _initialDestination);
+     127                 :       5632 :         redirectedExits[withdrawData] = ExitData(true, _newDestination, _newData);
+     128                 :            :     }
+     129                 :            : 
+     130                 :            :     function encodeWithdrawal(uint256 _exitNum, address _initialDestination)
+     131                 :            :         public
+     132                 :            :         pure
+     133                 :            :         returns (bytes32)
+     134                 :            :     {
+     135                 :            :         // here we assume the L2 bridge gives a unique exitNum to each exit
+     136                 :      12806 :         return keccak256(abi.encode(_exitNum, _initialDestination));
+     137                 :            :     }
+     138                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..f06d2d0644 --- /dev/null +++ b/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func-sort-c.html @@ -0,0 +1,137 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ArbitrumGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:394881.2 %
Date:2023-04-27 16:26:32Functions:111478.6 %
Branches:121866.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumGateway.createOutboundTx0
L1ArbitrumGateway.getExternalCall0
L1ArbitrumGateway.getOutboundCalldata0
L1ArbitrumGateway._initiateDeposit2
L1ArbitrumGateway.createOutboundTxCustomRefund2
L1ArbitrumGateway.inboundEscrowTransfer2
L1ArbitrumGateway.outboundTransfer2
L1ArbitrumGateway.postUpgradeInit2
L1ArbitrumGateway._parseUserEncodedData5
L1ArbitrumGateway.finalizeInboundTransfer6
L1ArbitrumGateway.outboundEscrowTransfer6
L1ArbitrumGateway.outboundTransferCustomRefund12
L1ArbitrumGateway._initialize13
L1ArbitrumGateway.supportsInterface512
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func.html b/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func.html new file mode 100644 index 0000000000..1824185b33 --- /dev/null +++ b/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func.html @@ -0,0 +1,137 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ArbitrumGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:394881.2 %
Date:2023-04-27 16:26:32Functions:111478.6 %
Branches:121866.7 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumGateway._initialize13
L1ArbitrumGateway._initiateDeposit2
L1ArbitrumGateway._parseUserEncodedData5
L1ArbitrumGateway.createOutboundTx0
L1ArbitrumGateway.createOutboundTxCustomRefund2
L1ArbitrumGateway.finalizeInboundTransfer6
L1ArbitrumGateway.getExternalCall0
L1ArbitrumGateway.getOutboundCalldata0
L1ArbitrumGateway.inboundEscrowTransfer2
L1ArbitrumGateway.outboundEscrowTransfer6
L1ArbitrumGateway.outboundTransfer2
L1ArbitrumGateway.outboundTransferCustomRefund12
L1ArbitrumGateway.postUpgradeInit2
L1ArbitrumGateway.supportsInterface512
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ArbitrumGateway.sol.gcov.html b/coverage/ethereum/gateway/L1ArbitrumGateway.sol.gcov.html new file mode 100644 index 0000000000..301e533ff0 --- /dev/null +++ b/coverage/ethereum/gateway/L1ArbitrumGateway.sol.gcov.html @@ -0,0 +1,488 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ArbitrumGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:394881.2 %
Date:2023-04-27 16:26:32Functions:111478.6 %
Branches:121866.7 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+      22                 :            : import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
+      23                 :            : import "@openzeppelin/contracts/utils/Create2.sol";
+      24                 :            : import "@openzeppelin/contracts/utils/Address.sol";
+      25                 :            : import "../L1ArbitrumMessenger.sol";
+      26                 :            : import "./IL1ArbitrumGateway.sol";
+      27                 :            : import "../../libraries/ProxyUtil.sol";
+      28                 :            : import "../../libraries/gateway/GatewayMessageHandler.sol";
+      29                 :            : import "../../libraries/gateway/TokenGateway.sol";
+      30                 :            : import "../../libraries/ITransferAndCall.sol";
+      31                 :            : import "../../libraries/ERC165.sol";
+      32                 :            : 
+      33                 :            : /**
+      34                 :            :  * @title Common interface for gatways on L1 messaging to Arbitrum.
+      35                 :            :  */
+      36                 :            : abstract contract L1ArbitrumGateway is
+      37                 :            :     L1ArbitrumMessenger,
+      38                 :            :     TokenGateway,
+      39                 :            :     ERC165,
+      40                 :            :     IL1ArbitrumGateway
+      41                 :            : {
+      42                 :            :     using SafeERC20 for IERC20;
+      43                 :            :     using Address for address;
+      44                 :            : 
+      45                 :            :     address public override inbox;
+      46                 :            : 
+      47                 :            :     event DepositInitiated(
+      48                 :            :         address l1Token,
+      49                 :            :         address indexed _from,
+      50                 :            :         address indexed _to,
+      51                 :            :         uint256 indexed _sequenceNumber,
+      52                 :            :         uint256 _amount
+      53                 :            :     );
+      54                 :            : 
+      55                 :            :     event WithdrawalFinalized(
+      56                 :            :         address l1Token,
+      57                 :            :         address indexed _from,
+      58                 :            :         address indexed _to,
+      59                 :            :         uint256 indexed _exitNum,
+      60                 :            :         uint256 _amount
+      61                 :            :     );
+      62                 :            : 
+      63                 :            :     modifier onlyCounterpartGateway() override {
+      64                 :            :         address _inbox = inbox;
+      65                 :            : 
+      66                 :            :         // a message coming from the counterpart gateway was executed by the bridge
+      67                 :            :         address bridge = address(super.getBridge(_inbox));
+      68                 :            :         require(msg.sender == bridge, "NOT_FROM_BRIDGE");
+      69                 :            : 
+      70                 :            :         // and the outbox reports that the L2 address of the sender is the counterpart gateway
+      71                 :            :         address l2ToL1Sender = super.getL2ToL1Sender(_inbox);
+      72                 :            :         require(l2ToL1Sender == counterpartGateway, "ONLY_COUNTERPART_GATEWAY");
+      73                 :            :         _;
+      74                 :            :     }
+      75                 :            : 
+      76                 :            :     function postUpgradeInit() external {
+      77                 :            :         // it is assumed the L1 Arbitrum Gateway contract is behind a Proxy controlled by a proxy admin
+      78                 :            :         // this function can only be called by the proxy admin contract
+      79                 :          2 :         address proxyAdmin = ProxyUtil.getProxyAdmin();
+      80         [ +  # ]:          2 :         require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");
+      81                 :            :         // this has no other logic since the current upgrade doesn't require this logic
+      82                 :            :     }
+      83                 :            : 
+      84                 :            :     function _initialize(
+      85                 :            :         address _l2Counterpart,
+      86                 :            :         address _router,
+      87                 :            :         address _inbox
+      88                 :            :     ) internal {
+      89                 :         13 :         TokenGateway._initialize(_l2Counterpart, _router);
+      90                 :            :         // L1 gateway must have a router
+      91         [ #  + ]:         13 :         require(_router != address(0), "BAD_ROUTER");
+      92         [ #  + ]:         13 :         require(_inbox != address(0), "BAD_INBOX");
+      93                 :         13 :         inbox = _inbox;
+      94                 :            :     }
+      95                 :            : 
+      96                 :            :     /**
+      97                 :            :      * @notice Finalizes a withdrawal via Outbox message; callable only by L2Gateway.outboundTransfer
+      98                 :            :      * @param _token L1 address of token being withdrawn from
+      99                 :            :      * @param _from initiator of withdrawal
+     100                 :            :      * @param _to address the L2 withdrawal call set as the destination.
+     101                 :            :      * @param _amount Token amount being withdrawn
+     102                 :            :      * @param _data encoded exitNum (Sequentially increasing exit counter determined by the L2Gateway) and additinal hook data
+     103                 :            :      */
+     104                 :            :     function finalizeInboundTransfer(
+     105                 :            :         address _token,
+     106                 :            :         address _from,
+     107                 :            :         address _to,
+     108                 :            :         uint256 _amount,
+     109                 :            :         bytes calldata _data
+     110                 :            :     ) public payable virtual override onlyCounterpartGateway {
+     111                 :            :         // this function is marked as virtual so superclasses can override it to add modifiers
+     112                 :          2 :         (uint256 exitNum, bytes memory callHookData) = GatewayMessageHandler.parseToL1GatewayMsg(
+     113                 :            :             _data
+     114                 :            :         );
+     115                 :            : 
+     116         [ #  + ]:          2 :         if (callHookData.length != 0) {
+     117                 :            :             // callHookData should always be 0 since inboundEscrowAndCall is disabled
+     118                 :          0 :             callHookData = bytes("");
+     119                 :            :         }
+     120                 :            : 
+     121                 :            :         // we ignore the returned data since the callHook feature is now disabled
+     122                 :          2 :         (_to, ) = getExternalCall(exitNum, _to, callHookData);
+     123                 :          2 :         inboundEscrowTransfer(_token, _to, _amount);
+     124                 :            : 
+     125                 :          2 :         emit WithdrawalFinalized(_token, _from, _to, exitNum, _amount);
+     126                 :            :     }
+     127                 :            : 
+     128                 :            :     function getExternalCall(
+     129                 :            :         uint256, /* _exitNum */
+     130                 :            :         address _initialDestination,
+     131                 :            :         bytes memory _initialData
+     132                 :            :     ) public view virtual returns (address target, bytes memory data) {
+     133                 :            :         // this method is virtual so the destination of a call can be changed
+     134                 :            :         // using tradeable exits in a subclass (L1ArbitrumExtendedGateway)
+     135                 :          0 :         target = _initialDestination;
+     136                 :          0 :         data = _initialData;
+     137                 :            :     }
+     138                 :            : 
+     139                 :            :     function inboundEscrowTransfer(
+     140                 :            :         address _l1Token,
+     141                 :            :         address _dest,
+     142                 :            :         uint256 _amount
+     143                 :            :     ) internal virtual {
+     144                 :            :         // this method is virtual since different subclasses can handle escrow differently
+     145                 :          2 :         IERC20(_l1Token).safeTransfer(_dest, _amount);
+     146                 :            :     }
+     147                 :            : 
+     148                 :            :     /**
+     149                 :            :      * @dev Only excess gas is refunded to the _refundTo account, l2 call value is always returned to the _to account
+     150                 :            :      */
+     151                 :            :     function createOutboundTxCustomRefund(
+     152                 :            :         address _refundTo,
+     153                 :            :         address _from,
+     154                 :            :         uint256, /* _tokenAmount */
+     155                 :            :         uint256 _maxGas,
+     156                 :            :         uint256 _gasPriceBid,
+     157                 :            :         uint256 _maxSubmissionCost,
+     158                 :            :         bytes memory _outboundCalldata
+     159                 :            :     ) internal virtual returns (uint256) {
+     160                 :            :         // We make this function virtual since outboundTransfer logic is the same for many gateways
+     161                 :            :         // but sometimes (ie weth) you construct the outgoing message differently.
+     162                 :            : 
+     163                 :            :         // msg.value is sent, but 0 is set to the L2 call value
+     164                 :            :         // the eth sent is used to pay for the tx's gas
+     165                 :          2 :         return
+     166                 :            :             sendTxToL2CustomRefund(
+     167                 :            :                 inbox,
+     168                 :            :                 counterpartGateway,
+     169                 :            :                 _refundTo,
+     170                 :            :                 _from,
+     171                 :            :                 msg.value, // we forward the L1 call value to the inbox
+     172                 :            :                 0, // l2 call value 0 by default
+     173                 :            :                 L2GasParams({
+     174                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
+     175                 :            :                     _maxGas: _maxGas,
+     176                 :            :                     _gasPriceBid: _gasPriceBid
+     177                 :            :                 }),
+     178                 :            :                 _outboundCalldata
+     179                 :            :             );
+     180                 :            :     }
+     181                 :            : 
+     182                 :            :     /**
+     183                 :            :      * @notice DEPRECATED - look at createOutboundTxCustomRefund instead
+     184                 :            :      */
+     185                 :            :     function createOutboundTx(
+     186                 :            :         address _from,
+     187                 :            :         uint256 _tokenAmount,
+     188                 :            :         uint256 _maxGas,
+     189                 :            :         uint256 _gasPriceBid,
+     190                 :            :         uint256 _maxSubmissionCost,
+     191                 :            :         bytes memory _outboundCalldata
+     192                 :            :     ) internal returns (uint256) {
+     193                 :          0 :         return
+     194                 :            :             createOutboundTxCustomRefund(
+     195                 :            :                 _from,
+     196                 :            :                 _from,
+     197                 :            :                 _tokenAmount,
+     198                 :            :                 _maxGas,
+     199                 :            :                 _gasPriceBid,
+     200                 :            :                 _maxSubmissionCost,
+     201                 :            :                 _outboundCalldata
+     202                 :            :             );
+     203                 :            :     }
+     204                 :            : 
+     205                 :            :     /**
+     206                 :            :      * @notice DEPRECATED - look at outboundTransferCustomRefund instead
+     207                 :            :      */
+     208                 :            :     function outboundTransfer(
+     209                 :            :         address _l1Token,
+     210                 :            :         address _to,
+     211                 :            :         uint256 _amount,
+     212                 :            :         uint256 _maxGas,
+     213                 :            :         uint256 _gasPriceBid,
+     214                 :            :         bytes calldata _data
+     215                 :            :     ) public payable override returns (bytes memory res) {
+     216                 :          2 :         return
+     217                 :            :             outboundTransferCustomRefund(_l1Token, _to, _to, _amount, _maxGas, _gasPriceBid, _data);
+     218                 :            :     }
+     219                 :            : 
+     220                 :            :     /**
+     221                 :            :      * @notice Deposit ERC20 token from Ethereum into Arbitrum. If L2 side hasn't been deployed yet, includes name/symbol/decimals data for initial L2 deploy. Initiate by GatewayRouter.
+     222                 :            :      * @dev L2 address alias will not be applied to the following types of addresses on L1:
+     223                 :            :      *      - an externally-owned account
+     224                 :            :      *      - a contract in construction
+     225                 :            :      *      - an address where a contract will be created
+     226                 :            :      *      - an address where a contract lived, but was destroyed
+     227                 :            :      * @param _l1Token L1 address of ERC20
+     228                 :            :      * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2
+     229                 :            :      * @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
+     230                 :            :                   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
+     231                 :            :      * @param _amount Token Amount
+     232                 :            :      * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution
+     233                 :            :      * @param _gasPriceBid Gas price for L2 execution
+     234                 :            :      * @param _data encoded data from router and user
+     235                 :            :      * @return res abi encoded inbox sequence number
+     236                 :            :      */
+     237                 :            :     //  * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
+     238                 :            :     function outboundTransferCustomRefund(
+     239                 :            :         address _l1Token,
+     240                 :            :         address _refundTo,
+     241                 :            :         address _to,
+     242                 :            :         uint256 _amount,
+     243                 :            :         uint256 _maxGas,
+     244                 :            :         uint256 _gasPriceBid,
+     245                 :            :         bytes calldata _data
+     246                 :            :     ) public payable virtual override returns (bytes memory res) {
+     247         [ +  + ]:         12 :         require(isRouter(msg.sender), "NOT_FROM_ROUTER");
+     248                 :            :         // This function is set as public and virtual so that subclasses can override
+     249                 :            :         // it and add custom validation for callers (ie only whitelisted users)
+     250                 :         10 :         address _from;
+     251                 :         10 :         uint256 seqNum;
+     252                 :         10 :         bytes memory extraData;
+     253                 :            :         {
+     254                 :         10 :             uint256 _maxSubmissionCost;
+     255                 :         10 :             uint256 tokenTotalFeeAmount;
+     256         [ +  # ]:         10 :             if (super.isRouter(msg.sender)) {
+     257                 :            :                 // router encoded
+     258                 :         10 :                 (_from, extraData) = GatewayMessageHandler.parseFromRouterToGateway(_data);
+     259                 :            :             } else {
+     260                 :          0 :                 _from = msg.sender;
+     261                 :          0 :                 extraData = _data;
+     262                 :            :             }
+     263                 :            :             // unpack user encoded data
+     264                 :         10 :             (_maxSubmissionCost, extraData, tokenTotalFeeAmount) = _parseUserEncodedData(extraData);
+     265                 :            : 
+     266                 :            :             // the inboundEscrowAndCall functionality has been disabled, so no data is allowed
+     267         [ +  + ]:         10 :             require(extraData.length == 0, "EXTRA_DATA_DISABLED");
+     268                 :            : 
+     269         [ +  + ]:          8 :             require(_l1Token.isContract(), "L1_NOT_CONTRACT");
+     270                 :          6 :             address l2Token = calculateL2TokenAddress(_l1Token);
+     271         [ #  + ]:          6 :             require(l2Token != address(0), "NO_L2_TOKEN_SET");
+     272                 :            : 
+     273                 :          6 :             _amount = outboundEscrowTransfer(_l1Token, _from, _amount);
+     274                 :            : 
+     275                 :            :             // we override the res field to save on the stack
+     276                 :          4 :             res = getOutboundCalldata(_l1Token, _from, _to, _amount, extraData);
+     277                 :            : 
+     278                 :          4 :             seqNum = _initiateDeposit(
+     279                 :            :                 _refundTo,
+     280                 :            :                 _from,
+     281                 :            :                 _amount,
+     282                 :            :                 _maxGas,
+     283                 :            :                 _gasPriceBid,
+     284                 :            :                 _maxSubmissionCost,
+     285                 :            :                 tokenTotalFeeAmount,
+     286                 :            :                 res
+     287                 :            :             );
+     288                 :            :         }
+     289                 :          4 :         emit DepositInitiated(_l1Token, _from, _to, seqNum, _amount);
+     290                 :          4 :         return abi.encode(seqNum);
+     291                 :            :     }
+     292                 :            : 
+     293                 :            :     function outboundEscrowTransfer(
+     294                 :            :         address _l1Token,
+     295                 :            :         address _from,
+     296                 :            :         uint256 _amount
+     297                 :            :     ) internal virtual returns (uint256 amountReceived) {
+     298                 :            :         // this method is virtual since different subclasses can handle escrow differently
+     299                 :            :         // user funds are escrowed on the gateway using this function
+     300                 :          6 :         uint256 prevBalance = IERC20(_l1Token).balanceOf(address(this));
+     301                 :          6 :         IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);
+     302                 :          4 :         uint256 postBalance = IERC20(_l1Token).balanceOf(address(this));
+     303                 :          4 :         return postBalance - prevBalance;
+     304                 :            :     }
+     305                 :            : 
+     306                 :            :     function getOutboundCalldata(
+     307                 :            :         address _l1Token,
+     308                 :            :         address _from,
+     309                 :            :         address _to,
+     310                 :            :         uint256 _amount,
+     311                 :            :         bytes memory _data
+     312                 :            :     ) public view virtual override returns (bytes memory outboundCalldata) {
+     313                 :            :         // this function is public so users can query how much calldata will be sent to the L2
+     314                 :            :         // before execution
+     315                 :            :         // it is virtual since different gateway subclasses can build this calldata differently
+     316                 :            :         // ( ie the standard ERC20 gateway queries for a tokens name/symbol/decimals )
+     317                 :          0 :         bytes memory emptyBytes = "";
+     318                 :            : 
+     319                 :          0 :         outboundCalldata = abi.encodeWithSelector(
+     320                 :            :             ITokenGateway.finalizeInboundTransfer.selector,
+     321                 :            :             _l1Token,
+     322                 :            :             _from,
+     323                 :            :             _to,
+     324                 :            :             _amount,
+     325                 :            :             GatewayMessageHandler.encodeToL2GatewayMsg(emptyBytes, _data)
+     326                 :            :         );
+     327                 :            : 
+     328                 :          0 :         return outboundCalldata;
+     329                 :            :     }
+     330                 :            : 
+     331                 :            :     function supportsInterface(bytes4 interfaceId)
+     332                 :            :         public
+     333                 :            :         view
+     334                 :            :         virtual
+     335                 :            :         override(ERC165, IERC165)
+     336                 :            :         returns (bool)
+     337                 :            :     {
+     338                 :            :         // registering interfaces that is added after arb-bridge-peripherals >1.0.11
+     339                 :            :         // using function selector instead of single function interfaces to reduce bloat
+     340                 :        512 :         return
+     341                 :            :             interfaceId == this.outboundTransferCustomRefund.selector ||
+     342                 :            :             super.supportsInterface(interfaceId);
+     343                 :            :     }
+     344                 :            : 
+     345                 :            :     /**
+     346                 :            :      * @notice Parse data that was encoded by user and passed into the outbound TX entrypoint
+     347                 :            :      * @dev In case of standard ETH-based rollup, format of encoded data is expected to be:
+     348                 :            :      *      - maxSubmissionCost (uint256)
+     349                 :            :      *      - callHookData (bytes)
+     350                 :            :      *      In case of ERC20-based rollup, format of encoded data is expected to be:
+     351                 :            :      *      - maxSubmissionCost (uint256)
+     352                 :            :      *      - tokenTotalFeeAmount (uint256)
+     353                 :            :      *      - callHookData (bytes)
+     354                 :            :      * @param data data encoded by user
+     355                 :            :      * @return maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
+     356                 :            :      * @return callHookData Calldata for extra call in inboundEscrowAndCall on L2
+     357                 :            :      * @return tokenTotalFeeAmount Amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups, otherwise 0)
+     358                 :            :      */
+     359                 :            :     function _parseUserEncodedData(
+     360                 :            :         bytes memory data
+     361                 :            :     )
+     362                 :            :         internal
+     363                 :            :         pure
+     364                 :            :         virtual
+     365                 :            :         returns (uint256 maxSubmissionCost, bytes memory callHookData, uint256 tokenTotalFeeAmount)
+     366                 :            :     {
+     367                 :          5 :         (maxSubmissionCost, callHookData) = abi.decode(data, (uint256, bytes));
+     368                 :            :     }
+     369                 :            : 
+     370                 :            :     /**
+     371                 :            :      * @notice Intermediate internal function that passes on parameters needed to trigger creation of retryable ticket.
+     372                 :            :      * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2
+     373                 :            :      * @param _from Initiator of deposit
+     374                 :            :      * @param _amount Token of token being deposited
+     375                 :            :      * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution
+     376                 :            :      * @param _gasPriceBid Gas price for L2 execution
+     377                 :            :      * @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
+     378                 :            :      * //param tokenTotalFeeAmount Amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups)
+     379                 :            :      * @param _data encoded data from router and user
+     380                 :            :      * @return res abi encoded inbox sequence number
+     381                 :            :      */
+     382                 :            :     function _initiateDeposit(
+     383                 :            :         address _refundTo,
+     384                 :            :         address _from,
+     385                 :            :         uint256 _amount,
+     386                 :            :         uint256 _maxGas,
+     387                 :            :         uint256 _gasPriceBid,
+     388                 :            :         uint256 _maxSubmissionCost,
+     389                 :            :         uint256, // tokenTotalFeeAmount
+     390                 :            :         bytes memory _data
+     391                 :            :     ) internal virtual returns (uint256) {
+     392                 :          2 :         return
+     393                 :            :             createOutboundTxCustomRefund(
+     394                 :            :                 _refundTo,
+     395                 :            :                 _from,
+     396                 :            :                 _amount,
+     397                 :            :                 _maxGas,
+     398                 :            :                 _gasPriceBid,
+     399                 :            :                 _maxSubmissionCost,
+     400                 :            :                 _data
+     401                 :            :             );
+     402                 :            :     }
+     403                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1CustomGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1CustomGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..b942e63372 --- /dev/null +++ b/coverage/ethereum/gateway/L1CustomGateway.sol.func-sort-c.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1CustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:162857.1 %
Date:2023-04-27 16:26:32Functions:3742.9 %
Branches:11010.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1CustomGateway.finalizeInboundTransfer0
L1CustomGateway.forceRegisterTokenToL20
L1CustomGateway.outboundTransferCustomRefund0
L1CustomGateway.setOwner0
L1CustomGateway.initialize6
L1CustomGateway.registerTokenToL26
L1CustomGateway.calculateL2TokenAddress7
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1CustomGateway.sol.func.html b/coverage/ethereum/gateway/L1CustomGateway.sol.func.html new file mode 100644 index 0000000000..fe33feb218 --- /dev/null +++ b/coverage/ethereum/gateway/L1CustomGateway.sol.func.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1CustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:162857.1 %
Date:2023-04-27 16:26:32Functions:3742.9 %
Branches:11010.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1CustomGateway.calculateL2TokenAddress7
L1CustomGateway.finalizeInboundTransfer0
L1CustomGateway.forceRegisterTokenToL20
L1CustomGateway.initialize6
L1CustomGateway.outboundTransferCustomRefund0
L1CustomGateway.registerTokenToL26
L1CustomGateway.setOwner0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1CustomGateway.sol.gcov.html b/coverage/ethereum/gateway/L1CustomGateway.sol.gcov.html new file mode 100644 index 0000000000..d150f0f873 --- /dev/null +++ b/coverage/ethereum/gateway/L1CustomGateway.sol.gcov.html @@ -0,0 +1,328 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1CustomGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:162857.1 %
Date:2023-04-27 16:26:32Functions:3742.9 %
Branches:11010.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import { ArbitrumEnabledToken } from "../ICustomToken.sol";
+      22                 :            : import "./L1ArbitrumExtendedGateway.sol";
+      23                 :            : import "../../arbitrum/gateway/L2CustomGateway.sol";
+      24                 :            : import "../../libraries/gateway/ICustomGateway.sol";
+      25                 :            : import "@openzeppelin/contracts/utils/Address.sol";
+      26                 :            : 
+      27                 :            : import "../../libraries/Whitelist.sol";
+      28                 :            : 
+      29                 :            : /**
+      30                 :            :  * @title Gatway for "custom" bridging functionality
+      31                 :            :  * @notice Handles some (but not all!) custom Gateway needs.
+      32                 :            :  */
+      33                 :            : contract L1CustomGateway is L1ArbitrumExtendedGateway, ICustomGateway {
+      34                 :            :     using Address for address;
+      35                 :            :     // stores addresses of L2 tokens to be used
+      36                 :            :     mapping(address => address) public override l1ToL2Token;
+      37                 :            :     // owner is able to force add custom mappings
+      38                 :            :     address public owner;
+      39                 :            : 
+      40                 :            :     // whitelist not used anymore
+      41                 :            :     address public whitelist;
+      42                 :            : 
+      43                 :            :     // start of inline reentrancy guard
+      44                 :            :     // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.2/contracts/utils/ReentrancyGuard.sol
+      45                 :            :     uint256 private constant _NOT_ENTERED = 1;
+      46                 :            :     uint256 private constant _ENTERED = 2;
+      47                 :            :     uint256 private _status;
+      48                 :            : 
+      49                 :            :     modifier nonReentrant() {
+      50                 :            :         // On the first call to nonReentrant, _notEntered will be true
+      51                 :            :         require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
+      52                 :            :         // Any calls to nonReentrant after this point will fail
+      53                 :            :         _status = _ENTERED;
+      54                 :            :         _;
+      55                 :            :         _status = _NOT_ENTERED;
+      56                 :            :     }
+      57                 :            : 
+      58                 :            :     modifier onlyOwner() {
+      59                 :            :         require(msg.sender == owner, "ONLY_OWNER");
+      60                 :            :         _;
+      61                 :            :     }
+      62                 :            : 
+      63                 :            :     function outboundTransferCustomRefund(
+      64                 :            :         address _l1Token,
+      65                 :            :         address _refundTo,
+      66                 :            :         address _to,
+      67                 :            :         uint256 _amount,
+      68                 :            :         uint256 _maxGas,
+      69                 :            :         uint256 _gasPriceBid,
+      70                 :            :         bytes calldata _data
+      71                 :            :     ) public payable override nonReentrant returns (bytes memory res) {
+      72                 :          0 :         return
+      73                 :            :             super.outboundTransferCustomRefund(
+      74                 :            :                 _l1Token,
+      75                 :            :                 _refundTo,
+      76                 :            :                 _to,
+      77                 :            :                 _amount,
+      78                 :            :                 _maxGas,
+      79                 :            :                 _gasPriceBid,
+      80                 :            :                 _data
+      81                 :            :             );
+      82                 :            :     }
+      83                 :            : 
+      84                 :            :     function finalizeInboundTransfer(
+      85                 :            :         address _token,
+      86                 :            :         address _from,
+      87                 :            :         address _to,
+      88                 :            :         uint256 _amount,
+      89                 :            :         bytes calldata _data
+      90                 :            :     ) public payable override nonReentrant {
+      91                 :            :         // the superclass checks onlyCounterpartGateway
+      92                 :          0 :         super.finalizeInboundTransfer(_token, _from, _to, _amount, _data);
+      93                 :            :     }
+      94                 :            : 
+      95                 :            :     function initialize(
+      96                 :            :         address _l1Counterpart,
+      97                 :            :         address _l1Router,
+      98                 :            :         address _inbox,
+      99                 :            :         address _owner
+     100                 :            :     ) public {
+     101                 :          6 :         L1ArbitrumGateway._initialize(_l1Counterpart, _l1Router, _inbox);
+     102                 :          6 :         owner = _owner;
+     103                 :            :         // disable whitelist by default
+     104                 :          6 :         whitelist = address(0);
+     105                 :            :         // reentrancy guard
+     106                 :          6 :         _status = _NOT_ENTERED;
+     107                 :            :     }
+     108                 :            : 
+     109                 :            :     /**
+     110                 :            :      * @notice Calculate the address used when bridging an ERC20 token
+     111                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
+     112                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
+     113                 :            :      * @param l1ERC20 address of L1 token
+     114                 :            :      * @return L2 address of a bridged ERC20 token
+     115                 :            :      */
+     116                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override(ITokenGateway, TokenGateway) returns (address) {
+     117                 :          7 :         return l1ToL2Token[l1ERC20];
+     118                 :            :     }
+     119                 :            : 
+     120                 :            :     /**
+     121                 :            :      * @notice Allows L1 Token contract to trustlessly register its custom L2 counterpart. (other registerTokenToL2 method allows excess eth recovery from _maxSubmissionCost and is recommended)
+     122                 :            :      * @param _l2Address counterpart address of L1 token
+     123                 :            :      * @param _maxGas max gas for L2 retryable exrecution
+     124                 :            :      * @param _gasPriceBid gas price for L2 retryable ticket
+     125                 :            :      * @param  _maxSubmissionCost base submission cost  L2 retryable tick3et
+     126                 :            :      * @return Retryable ticket ID
+     127                 :            :      */
+     128                 :            :     function registerTokenToL2(
+     129                 :            :         address _l2Address,
+     130                 :            :         uint256 _maxGas,
+     131                 :            :         uint256 _gasPriceBid,
+     132                 :            :         uint256 _maxSubmissionCost
+     133                 :            :     ) external payable returns (uint256) {
+     134                 :          0 :         return registerTokenToL2(_l2Address, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender);
+     135                 :            :     }
+     136                 :            : 
+     137                 :            :     /**
+     138                 :            :      * @notice Allows L1 Token contract to trustlessly register its custom L2 counterpart.
+     139                 :            :      * param _l2Address counterpart address of L1 token
+     140                 :            :      * param _maxGas max gas for L2 retryable exrecution
+     141                 :            :      * param _gasPriceBid gas price for L2 retryable ticket
+     142                 :            :      * param  _maxSubmissionCost base submission cost  L2 retryable tick3et
+     143                 :            :      * param _creditBackAddress address for crediting back overpayment of _maxSubmissionCost
+     144                 :            :      * return Retryable ticket ID
+     145                 :            :      */
+     146                 :            :     function registerTokenToL2(
+     147                 :            :         address _l2Address,
+     148                 :            :         uint256 _maxGas,
+     149                 :            :         uint256 _gasPriceBid,
+     150                 :            :         uint256 _maxSubmissionCost,
+     151                 :            :         address _creditBackAddress
+     152                 :            :     ) public payable virtual returns (uint256) {
+     153         [ #  + ]:          6 :         require(
+     154                 :            :             ArbitrumEnabledToken(msg.sender).isArbitrumEnabled() == uint8(0xb1),
+     155                 :            :             "NOT_ARB_ENABLED"
+     156                 :            :         );
+     157                 :            : 
+     158                 :          6 :         address currL2Addr = l1ToL2Token[msg.sender];
+     159         [ #  # ]:          6 :         if (currL2Addr != address(0)) {
+     160                 :            :             // if token is already set, don't allow it to set a different L2 address
+     161         [ #  # ]:          0 :             require(currL2Addr == _l2Address, "NO_UPDATE_TO_DIFFERENT_ADDR");
+     162                 :            :         }
+     163                 :            : 
+     164                 :          6 :         l1ToL2Token[msg.sender] = _l2Address;
+     165                 :            : 
+     166                 :          6 :         address[] memory l1Addresses = new address[](1);
+     167                 :          6 :         address[] memory l2Addresses = new address[](1);
+     168                 :          6 :         l1Addresses[0] = msg.sender;
+     169                 :          6 :         l2Addresses[0] = _l2Address;
+     170                 :            : 
+     171                 :          6 :         emit TokenSet(l1Addresses[0], l2Addresses[0]);
+     172                 :            : 
+     173                 :          6 :         bytes memory _data = abi.encodeWithSelector(
+     174                 :            :             L2CustomGateway.registerTokenFromL1.selector,
+     175                 :            :             l1Addresses,
+     176                 :            :             l2Addresses
+     177                 :            :         );
+     178                 :            : 
+     179                 :          6 :         return
+     180                 :            :             sendTxToL2(
+     181                 :            :                 inbox,
+     182                 :            :                 counterpartGateway,
+     183                 :            :                 _creditBackAddress,
+     184                 :            :                 msg.value,
+     185                 :            :                 0,
+     186                 :            :                 _maxSubmissionCost,
+     187                 :            :                 _maxGas,
+     188                 :            :                 _gasPriceBid,
+     189                 :            :                 _data
+     190                 :            :             );
+     191                 :            :     }
+     192                 :            : 
+     193                 :            :     function setOwner(address newOwner) external onlyOwner {
+     194         [ #  # ]:          0 :         require(newOwner != address(0), "INVALID_OWNER");
+     195                 :          0 :         owner = newOwner;
+     196                 :            :     }
+     197                 :            : 
+     198                 :            :     /**
+     199                 :            :      * @notice Allows owner to force register a custom L1/L2 token pair.
+     200                 :            :      * @dev _l1Addresses[i] counterpart is assumed to be _l2Addresses[i]
+     201                 :            :      * @param _l1Addresses array of L1 addresses
+     202                 :            :      * @param _l2Addresses array of L2 addresses
+     203                 :            :      * @param _maxGas max gas for L2 retryable exrecution
+     204                 :            :      * @param _gasPriceBid gas price for L2 retryable ticket
+     205                 :            :      * @param  _maxSubmissionCost base submission cost  L2 retryable tick3et
+     206                 :            :      * @return Retryable ticket ID
+     207                 :            :      */
+     208                 :            :     function forceRegisterTokenToL2(
+     209                 :            :         address[] calldata _l1Addresses,
+     210                 :            :         address[] calldata _l2Addresses,
+     211                 :            :         uint256 _maxGas,
+     212                 :            :         uint256 _gasPriceBid,
+     213                 :            :         uint256 _maxSubmissionCost
+     214                 :            :     ) external payable onlyOwner returns (uint256) {
+     215         [ #  # ]:          0 :         require(_l1Addresses.length == _l2Addresses.length, "INVALID_LENGTHS");
+     216                 :            : 
+     217                 :          0 :         for (uint256 i = 0; i < _l1Addresses.length; i++) {
+     218                 :            :             // here we assume the owner checked both addresses offchain before force registering
+     219                 :            :             // require(address(_l1Addresses[i]).isContract(), "MUST_BE_CONTRACT");
+     220                 :          0 :             l1ToL2Token[_l1Addresses[i]] = _l2Addresses[i];
+     221                 :          0 :             emit TokenSet(_l1Addresses[i], _l2Addresses[i]);
+     222                 :            :         }
+     223                 :            : 
+     224                 :          0 :         bytes memory _data = abi.encodeWithSelector(
+     225                 :            :             L2CustomGateway.registerTokenFromL1.selector,
+     226                 :            :             _l1Addresses,
+     227                 :            :             _l2Addresses
+     228                 :            :         );
+     229                 :            : 
+     230                 :          0 :         return
+     231                 :            :             sendTxToL2(
+     232                 :            :                 inbox,
+     233                 :            :                 counterpartGateway,
+     234                 :            :                 msg.sender,
+     235                 :            :                 msg.value,
+     236                 :            :                 0,
+     237                 :            :                 _maxSubmissionCost,
+     238                 :            :                 _maxGas,
+     239                 :            :                 _gasPriceBid,
+     240                 :            :                 _data
+     241                 :            :             );
+     242                 :            :     }
+     243                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ERC20Gateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ERC20Gateway.sol.func-sort-c.html new file mode 100644 index 0000000000..6fc20e1578 --- /dev/null +++ b/coverage/ethereum/gateway/L1ERC20Gateway.sol.func-sort-c.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ERC20Gateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1818100.0 %
Date:2023-04-27 16:26:32Functions:77100.0 %
Branches:44100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ERC20Gateway.finalizeInboundTransfer6
L1ERC20Gateway.getOutboundCalldata6
L1ERC20Gateway.initialize7
L1ERC20Gateway.outboundTransferCustomRefund10
L1ERC20Gateway.callStatic30
L1ERC20Gateway.calculateL2TokenAddress512
L1ERC20Gateway.getSalt518
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ERC20Gateway.sol.func.html b/coverage/ethereum/gateway/L1ERC20Gateway.sol.func.html new file mode 100644 index 0000000000..9853a7120a --- /dev/null +++ b/coverage/ethereum/gateway/L1ERC20Gateway.sol.func.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ERC20Gateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1818100.0 %
Date:2023-04-27 16:26:32Functions:77100.0 %
Branches:44100.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ERC20Gateway.calculateL2TokenAddress512
L1ERC20Gateway.callStatic30
L1ERC20Gateway.finalizeInboundTransfer6
L1ERC20Gateway.getOutboundCalldata6
L1ERC20Gateway.getSalt518
L1ERC20Gateway.initialize7
L1ERC20Gateway.outboundTransferCustomRefund10
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ERC20Gateway.sol.gcov.html b/coverage/ethereum/gateway/L1ERC20Gateway.sol.gcov.html new file mode 100644 index 0000000000..c9ddaff34e --- /dev/null +++ b/coverage/ethereum/gateway/L1ERC20Gateway.sol.gcov.html @@ -0,0 +1,246 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ERC20Gateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1818100.0 %
Date:2023-04-27 16:26:32Functions:77100.0 %
Branches:44100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./L1ArbitrumExtendedGateway.sol";
+      22                 :            : import "@openzeppelin/contracts/utils/Create2.sol";
+      23                 :            : import "../../libraries/Whitelist.sol";
+      24                 :            : 
+      25                 :            : /**
+      26                 :            :  * @title Layer 1 Gateway contract for bridging standard ERC20s
+      27                 :            :  * @notice This contract handles token deposits, holds the escrowed tokens on layer 1, and (ultimately) finalizes withdrawals.
+      28                 :            :  * @dev Any ERC20 that requires non-standard functionality should use a separate gateway.
+      29                 :            :  * Messages to layer 2 use the inbox's createRetryableTicket method.
+      30                 :            :  */
+      31                 :            : contract L1ERC20Gateway is L1ArbitrumExtendedGateway {
+      32                 :            :     // used for create2 address calculation
+      33                 :            :     bytes32 public cloneableProxyHash;
+      34                 :            :     // We don't use the solidity creationCode as it breaks when upgrading contracts
+      35                 :            :     // keccak256(type(ClonableBeaconProxy).creationCode);
+      36                 :            :     address public l2BeaconProxyFactory;
+      37                 :            :     // whitelist not used anymore
+      38                 :            :     address public whitelist;
+      39                 :            : 
+      40                 :            :     // start of inline reentrancy guard
+      41                 :            :     // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.2/contracts/utils/ReentrancyGuard.sol
+      42                 :            :     uint256 private constant _NOT_ENTERED = 1;
+      43                 :            :     uint256 private constant _ENTERED = 2;
+      44                 :            :     uint256 private _status;
+      45                 :            : 
+      46                 :            :     modifier nonReentrant() {
+      47                 :            :         // On the first call to nonReentrant, _notEntered will be true
+      48                 :            :         require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
+      49                 :            :         // Any calls to nonReentrant after this point will fail
+      50                 :            :         _status = _ENTERED;
+      51                 :            :         _;
+      52                 :            :         _status = _NOT_ENTERED;
+      53                 :            :     }
+      54                 :            : 
+      55                 :            :     // end of inline reentrancy guard
+      56                 :            : 
+      57                 :            :     function outboundTransferCustomRefund(
+      58                 :            :         address _l1Token,
+      59                 :            :         address _refundTo,
+      60                 :            :         address _to,
+      61                 :            :         uint256 _amount,
+      62                 :            :         uint256 _maxGas,
+      63                 :            :         uint256 _gasPriceBid,
+      64                 :            :         bytes calldata _data
+      65                 :            :     ) public payable override nonReentrant returns (bytes memory res) {
+      66                 :         12 :         return
+      67                 :            :             super.outboundTransferCustomRefund(
+      68                 :            :                 _l1Token,
+      69                 :            :                 _refundTo,
+      70                 :            :                 _to,
+      71                 :            :                 _amount,
+      72                 :            :                 _maxGas,
+      73                 :            :                 _gasPriceBid,
+      74                 :            :                 _data
+      75                 :            :             );
+      76                 :            :     }
+      77                 :            : 
+      78                 :            :     function finalizeInboundTransfer(
+      79                 :            :         address _token,
+      80                 :            :         address _from,
+      81                 :            :         address _to,
+      82                 :            :         uint256 _amount,
+      83                 :            :         bytes calldata _data
+      84                 :            :     ) public payable override nonReentrant {
+      85                 :            :         // the superclass checks onlyCounterpartGateway
+      86                 :          6 :         super.finalizeInboundTransfer(_token, _from, _to, _amount, _data);
+      87                 :            :     }
+      88                 :            : 
+      89                 :            :     function initialize(
+      90                 :            :         address _l2Counterpart,
+      91                 :            :         address _router,
+      92                 :            :         address _inbox,
+      93                 :            :         bytes32 _cloneableProxyHash,
+      94                 :            :         address _l2BeaconProxyFactory
+      95                 :            :     ) public {
+      96                 :          7 :         L1ArbitrumGateway._initialize(_l2Counterpart, _router, _inbox);
+      97         [ +  + ]:          7 :         require(_cloneableProxyHash != bytes32(0), "INVALID_PROXYHASH");
+      98         [ +  + ]:          5 :         require(_l2BeaconProxyFactory != address(0), "INVALID_BEACON");
+      99                 :          3 :         cloneableProxyHash = _cloneableProxyHash;
+     100                 :          3 :         l2BeaconProxyFactory = _l2BeaconProxyFactory;
+     101                 :            :         // disable whitelist by default
+     102                 :          3 :         whitelist = address(0);
+     103                 :            :         // reentrancy guard
+     104                 :          3 :         _status = _NOT_ENTERED;
+     105                 :            :     }
+     106                 :            : 
+     107                 :            :     /**
+     108                 :            :      * @notice utility function used to perform external read-only calls.
+     109                 :            :      * @dev the result is returned even if the call failed or was directed at an EOA,
+     110                 :            :      * it is cheaper to have the L2 consumer identify and deal with this.
+     111                 :            :      * @return result bytes, even if the call failed.
+     112                 :            :      */
+     113                 :            :     function callStatic(address targetContract, bytes4 targetFunction)
+     114                 :            :         internal
+     115                 :            :         view
+     116                 :            :         returns (bytes memory)
+     117                 :            :     {
+     118                 :         30 :         (
+     119                 :            :             ,
+     120                 :            :             /* bool success */
+     121                 :            :             bytes memory res
+     122                 :         30 :         ) = targetContract.staticcall(abi.encodeWithSelector(targetFunction));
+     123                 :         30 :         return res;
+     124                 :            :     }
+     125                 :            : 
+     126                 :            :     function getOutboundCalldata(
+     127                 :            :         address _token,
+     128                 :            :         address _from,
+     129                 :            :         address _to,
+     130                 :            :         uint256 _amount,
+     131                 :            :         bytes memory _data
+     132                 :            :     ) public view override returns (bytes memory outboundCalldata) {
+     133                 :            :         // TODO: cheaper to make static calls or save isDeployed to storage?
+     134                 :         10 :         bytes memory deployData = abi.encode(
+     135                 :            :             callStatic(_token, ERC20.name.selector),
+     136                 :            :             callStatic(_token, ERC20.symbol.selector),
+     137                 :            :             callStatic(_token, ERC20.decimals.selector)
+     138                 :            :         );
+     139                 :            : 
+     140                 :         10 :         outboundCalldata = abi.encodeWithSelector(
+     141                 :            :             ITokenGateway.finalizeInboundTransfer.selector,
+     142                 :            :             _token,
+     143                 :            :             _from,
+     144                 :            :             _to,
+     145                 :            :             _amount,
+     146                 :            :             GatewayMessageHandler.encodeToL2GatewayMsg(deployData, _data)
+     147                 :            :         );
+     148                 :            : 
+     149                 :         10 :         return outboundCalldata;
+     150                 :            :     }
+     151                 :            : 
+     152                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override(ITokenGateway, TokenGateway) returns (address) {
+     153                 :        518 :         bytes32 salt = getSalt(l1ERC20);
+     154                 :        518 :         return Create2.computeAddress(salt, cloneableProxyHash, l2BeaconProxyFactory);
+     155                 :            :     }
+     156                 :            : 
+     157                 :            :     function getSalt(address l1ERC20) internal view returns (bytes32) {
+     158                 :            :         // TODO: use a library
+     159                 :        518 :         return keccak256(abi.encode(counterpartGateway, keccak256(abi.encode(l1ERC20))));
+     160                 :            :     }
+     161                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..8a5c1e448b --- /dev/null +++ b/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ForceOnlyReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ForceOnlyReverseCustomGateway.registerTokenToL20
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func.html b/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func.html new file mode 100644 index 0000000000..25927b966f --- /dev/null +++ b/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ForceOnlyReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ForceOnlyReverseCustomGateway.registerTokenToL20
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.gcov.html b/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.gcov.html new file mode 100644 index 0000000000..f6d97d254c --- /dev/null +++ b/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.gcov.html @@ -0,0 +1,121 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ForceOnlyReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./L1ReverseCustomGateway.sol";
+      22                 :            : 
+      23                 :            : /**
+      24                 :            :  * @title An L1 Reverse gateway which only allows force registration
+      25                 :            :  */
+      26                 :            : contract L1ForceOnlyReverseCustomGateway is L1ReverseCustomGateway {
+      27                 :            :     function registerTokenToL2(
+      28                 :            :         address _l2Address,
+      29                 :            :         uint256 _maxGas,
+      30                 :            :         uint256 _gasPriceBid,
+      31                 :            :         uint256 _maxSubmissionCost,
+      32                 :            :         address _creditBackAddress
+      33                 :            :     ) public payable virtual override returns (uint256) {
+      34                 :          0 :         revert("REGISTER_TOKEN_ON_L2_DISABLED");
+      35                 :            :     }
+      36                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1GatewayRouter.sol.func-sort-c.html b/coverage/ethereum/gateway/L1GatewayRouter.sol.func-sort-c.html new file mode 100644 index 0000000000..1e0179e586 --- /dev/null +++ b/coverage/ethereum/gateway/L1GatewayRouter.sol.func-sort-c.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1GatewayRouter.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:354087.5 %
Date:2023-04-27 16:26:32Functions:7977.8 %
Branches:131872.2 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1GatewayRouter.outboundTransfer0
L1GatewayRouter.outboundTransferCustomRefund0
L1GatewayRouter.setDefaultGateway1
L1GatewayRouter.setGateways3
L1GatewayRouter.initialize4
L1GatewayRouter._setGateways7
L1GatewayRouter.setGateway8
L1GatewayRouter.supportsInterface256
L1GatewayRouter.setOwner258
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1GatewayRouter.sol.func.html b/coverage/ethereum/gateway/L1GatewayRouter.sol.func.html new file mode 100644 index 0000000000..a73094c070 --- /dev/null +++ b/coverage/ethereum/gateway/L1GatewayRouter.sol.func.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1GatewayRouter.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:354087.5 %
Date:2023-04-27 16:26:32Functions:7977.8 %
Branches:131872.2 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1GatewayRouter._setGateways7
L1GatewayRouter.initialize4
L1GatewayRouter.outboundTransfer0
L1GatewayRouter.outboundTransferCustomRefund0
L1GatewayRouter.setDefaultGateway1
L1GatewayRouter.setGateway8
L1GatewayRouter.setGateways3
L1GatewayRouter.setOwner258
L1GatewayRouter.supportsInterface256
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1GatewayRouter.sol.gcov.html b/coverage/ethereum/gateway/L1GatewayRouter.sol.gcov.html new file mode 100644 index 0000000000..576473a750 --- /dev/null +++ b/coverage/ethereum/gateway/L1GatewayRouter.sol.gcov.html @@ -0,0 +1,391 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1GatewayRouter.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:354087.5 %
Date:2023-04-27 16:26:32Functions:7977.8 %
Branches:131872.2 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../../libraries/Whitelist.sol";
+      22                 :            : 
+      23                 :            : import { ArbitrumEnabledToken } from "../ICustomToken.sol";
+      24                 :            : import "../L1ArbitrumMessenger.sol";
+      25                 :            : import "../../libraries/gateway/GatewayRouter.sol";
+      26                 :            : import "../../arbitrum/gateway/L2GatewayRouter.sol";
+      27                 :            : import "../../libraries/ERC165.sol";
+      28                 :            : import "./IL1GatewayRouter.sol";
+      29                 :            : import "./IL1ArbitrumGateway.sol";
+      30                 :            : 
+      31                 :            : /**
+      32                 :            :  * @title Handles deposits from Erhereum into Arbitrum. Tokens are routered to their appropriate L1 gateway (Router itself also conforms to the Gateway itnerface).
+      33                 :            :  * @notice Router also serves as an L1-L2 token address oracle.
+      34                 :            :  */
+      35                 :            : contract L1GatewayRouter is
+      36                 :            :     WhitelistConsumer,
+      37                 :            :     L1ArbitrumMessenger,
+      38                 :            :     GatewayRouter,
+      39                 :            :     ERC165,
+      40                 :            :     IL1GatewayRouter
+      41                 :            : {
+      42                 :            :     address public override owner;
+      43                 :            :     address public override inbox;
+      44                 :            : 
+      45                 :            :     modifier onlyOwner() {
+      46                 :            :         require(msg.sender == owner, "ONLY_OWNER");
+      47                 :            :         _;
+      48                 :            :     }
+      49                 :            : 
+      50                 :            :     function initialize(
+      51                 :            :         address _owner,
+      52                 :            :         address _defaultGateway,
+      53                 :            :         address, // was _whitelist, now unused
+      54                 :            :         address _counterpartGateway,
+      55                 :            :         address _inbox
+      56                 :            :     ) public {
+      57                 :          4 :         GatewayRouter._initialize(_counterpartGateway, address(0), _defaultGateway);
+      58                 :          2 :         owner = _owner;
+      59                 :          2 :         WhitelistConsumer.whitelist = address(0);
+      60                 :          2 :         inbox = _inbox;
+      61                 :            :     }
+      62                 :            : 
+      63                 :            :     function setDefaultGateway(
+      64                 :            :         address newL1DefaultGateway,
+      65                 :            :         uint256 _maxGas,
+      66                 :            :         uint256 _gasPriceBid,
+      67                 :            :         uint256 _maxSubmissionCost
+      68                 :            :     ) external payable onlyOwner returns (uint256) {
+      69                 :          1 :         defaultGateway = newL1DefaultGateway;
+      70                 :            : 
+      71                 :          1 :         emit DefaultGatewayUpdated(newL1DefaultGateway);
+      72                 :            : 
+      73                 :          1 :         address l2NewDefaultGateway;
+      74                 :            : 
+      75         [ #  + ]:          1 :         if (newL1DefaultGateway != address(0)) {
+      76                 :          1 :             l2NewDefaultGateway = TokenGateway(newL1DefaultGateway).counterpartGateway();
+      77                 :            :         }
+      78                 :            : 
+      79                 :          1 :         bytes memory data = abi.encodeWithSelector(
+      80                 :            :             L2GatewayRouter.setDefaultGateway.selector,
+      81                 :            :             l2NewDefaultGateway
+      82                 :            :         );
+      83                 :            : 
+      84                 :          1 :         return
+      85                 :            :             sendTxToL2(
+      86                 :            :                 inbox,
+      87                 :            :                 counterpartGateway,
+      88                 :            :                 msg.sender,
+      89                 :            :                 msg.value,
+      90                 :            :                 0,
+      91                 :            :                 L2GasParams({
+      92                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
+      93                 :            :                     _maxGas: _maxGas,
+      94                 :            :                     _gasPriceBid: _gasPriceBid
+      95                 :            :                 }),
+      96                 :            :                 data
+      97                 :            :             );
+      98                 :            :     }
+      99                 :            : 
+     100                 :            :     function setOwner(address newOwner) external onlyOwner {
+     101         [ +  + ]:        257 :         require(newOwner != address(0), "INVALID_OWNER");
+     102                 :            :         // set newOwner to address(1) to disable owner and keep `initialize` safe
+     103                 :        256 :         owner = newOwner;
+     104                 :            :     }
+     105                 :            : 
+     106                 :            :     function _setGateways(
+     107                 :            :         address[] memory _token,
+     108                 :            :         address[] memory _gateway,
+     109                 :            :         uint256 _maxGas,
+     110                 :            :         uint256 _gasPriceBid,
+     111                 :            :         uint256 _maxSubmissionCost,
+     112                 :            :         address _creditBackAddress
+     113                 :            :     ) internal returns (uint256) {
+     114         [ #  + ]:          7 :         require(_token.length == _gateway.length, "WRONG_LENGTH");
+     115                 :            : 
+     116                 :          7 :         for (uint256 i = 0; i < _token.length; i++) {
+     117                 :          8 :             l1TokenToGateway[_token[i]] = _gateway[i];
+     118                 :          8 :             emit GatewaySet(_token[i], _gateway[i]);
+     119                 :            :             // overwrite memory so the L2 router receives the L2 address of each gateway
+     120         [ #  + ]:          8 :             if (_gateway[i] != address(0) && _gateway[i] != DISABLED) {
+     121                 :            :                 // if we are assigning a gateway to the token, the address oracle of the gateway
+     122                 :            :                 // must return something other than the 0 address
+     123                 :            :                 // this check helps avoid misconfiguring gateways
+     124         [ +  + ]:          7 :                 require(
+     125                 :            :                     TokenGateway(_gateway[i]).calculateL2TokenAddress(_token[i]) != address(0),
+     126                 :            :                     "TOKEN_NOT_HANDLED_BY_GATEWAY"
+     127                 :            :                 );
+     128                 :          6 :                 _gateway[i] = TokenGateway(_gateway[i]).counterpartGateway();
+     129                 :            :             }
+     130                 :            :         }
+     131                 :            : 
+     132                 :          6 :         bytes memory data = abi.encodeWithSelector(
+     133                 :            :             L2GatewayRouter.setGateway.selector,
+     134                 :            :             _token,
+     135                 :            :             _gateway
+     136                 :            :         );
+     137                 :            : 
+     138                 :          6 :         return
+     139                 :            :             sendTxToL2(
+     140                 :            :                 inbox,
+     141                 :            :                 counterpartGateway,
+     142                 :            :                 _creditBackAddress,
+     143                 :            :                 msg.value,
+     144                 :            :                 0,
+     145                 :            :                 L2GasParams({
+     146                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
+     147                 :            :                     _maxGas: _maxGas,
+     148                 :            :                     _gasPriceBid: _gasPriceBid
+     149                 :            :                 }),
+     150                 :            :                 data
+     151                 :            :             );
+     152                 :            :     }
+     153                 :            : 
+     154                 :            :     /**
+     155                 :            :      * @notice Allows L1 Token contract to trustlessly register its gateway. (other setGateway method allows excess eth recovery from _maxSubmissionCost and is recommended)
+     156                 :            :      * @param _gateway l1 gateway address
+     157                 :            :      * @param _maxGas max gas for L2 retryable exrecution
+     158                 :            :      * @param _gasPriceBid gas price for L2 retryable ticket
+     159                 :            :      * @param  _maxSubmissionCost base submission cost  L2 retryable tick3et
+     160                 :            :      * @return Retryable ticket ID
+     161                 :            :      */
+     162                 :            :     function setGateway(
+     163                 :            :         address _gateway,
+     164                 :            :         uint256 _maxGas,
+     165                 :            :         uint256 _gasPriceBid,
+     166                 :            :         uint256 _maxSubmissionCost
+     167                 :            :     ) external payable override returns (uint256) {
+     168                 :          1 :         return setGateway(_gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender);
+     169                 :            :     }
+     170                 :            : 
+     171                 :            :     /**
+     172                 :            :      * @notice Allows L1 Token contract to trustlessly register its gateway.
+     173                 :            :      * @param _gateway l1 gateway address
+     174                 :            :      * @param _maxGas max gas for L2 retryable exrecution
+     175                 :            :      * @param _gasPriceBid gas price for L2 retryable ticket
+     176                 :            :      * @param  _maxSubmissionCost base submission cost  L2 retryable tick3et
+     177                 :            :      * @param _creditBackAddress address for crediting back overpayment of _maxSubmissionCost
+     178                 :            :      * @return Retryable ticket ID
+     179                 :            :      */
+     180                 :            :     function setGateway(
+     181                 :            :         address _gateway,
+     182                 :            :         uint256 _maxGas,
+     183                 :            :         uint256 _gasPriceBid,
+     184                 :            :         uint256 _maxSubmissionCost,
+     185                 :            :         address _creditBackAddress
+     186                 :            :     ) public payable override returns (uint256) {
+     187         [ +  + ]:          8 :         require(
+     188                 :            :             ArbitrumEnabledToken(msg.sender).isArbitrumEnabled() == uint8(0xb1),
+     189                 :            :             "NOT_ARB_ENABLED"
+     190                 :            :         );
+     191                 :            : 
+     192         [ +  + ]:          7 :         require(Address.isContract(_gateway), "NOT_TO_CONTRACT");
+     193                 :            : 
+     194                 :          6 :         address currGateway = getGateway(msg.sender);
+     195         [ +  # ]:          6 :         if (currGateway != address(0) && currGateway != defaultGateway) {
+     196                 :            :             // if gateway is already set to a non-default gateway, don't allow it to set a different gateway
+     197         [ +  # ]:          1 :             require(currGateway == _gateway, "NO_UPDATE_TO_DIFFERENT_ADDR");
+     198                 :            :         }
+     199                 :            : 
+     200                 :          5 :         address[] memory _tokenArr = new address[](1);
+     201                 :          5 :         _tokenArr[0] = address(msg.sender);
+     202                 :            : 
+     203                 :          5 :         address[] memory _gatewayArr = new address[](1);
+     204                 :          5 :         _gatewayArr[0] = _gateway;
+     205                 :            : 
+     206                 :          5 :         return
+     207                 :            :             _setGateways(
+     208                 :            :                 _tokenArr,
+     209                 :            :                 _gatewayArr,
+     210                 :            :                 _maxGas,
+     211                 :            :                 _gasPriceBid,
+     212                 :            :                 _maxSubmissionCost,
+     213                 :            :                 _creditBackAddress
+     214                 :            :             );
+     215                 :            :     }
+     216                 :            : 
+     217                 :            :     function setGateways(
+     218                 :            :         address[] memory _token,
+     219                 :            :         address[] memory _gateway,
+     220                 :            :         uint256 _maxGas,
+     221                 :            :         uint256 _gasPriceBid,
+     222                 :            :         uint256 _maxSubmissionCost
+     223                 :            :     ) external payable onlyOwner returns (uint256) {
+     224                 :            :         // it is assumed that token and gateway are both contracts
+     225                 :            :         // require(_token[i].isContract() && _gateway[i].isContract(), "NOT_CONTRACT");
+     226                 :          2 :         return
+     227                 :            :             _setGateways(_token, _gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender);
+     228                 :            :     }
+     229                 :            : 
+     230                 :            :     function outboundTransfer(
+     231                 :            :         address _token,
+     232                 :            :         address _to,
+     233                 :            :         uint256 _amount,
+     234                 :            :         uint256 _maxGas,
+     235                 :            :         uint256 _gasPriceBid,
+     236                 :            :         bytes calldata _data
+     237                 :            :     ) public payable override(GatewayRouter, ITokenGateway) returns (bytes memory) {
+     238                 :          0 :         return super.outboundTransfer(_token, _to, _amount, _maxGas, _gasPriceBid, _data);
+     239                 :            :     }
+     240                 :            : 
+     241                 :            :     /**
+     242                 :            :      * @notice Deposit ERC20 token from Ethereum into Arbitrum using the registered or otherwise default gateway
+     243                 :            :      * @dev Some legacy gateway might not have the outboundTransferCustomRefund method and will revert, in such case use outboundTransfer instead
+     244                 :            :      *      L2 address alias will not be applied to the following types of addresses on L1:
+     245                 :            :      *      - an externally-owned account
+     246                 :            :      *      - a contract in construction
+     247                 :            :      *      - an address where a contract will be created
+     248                 :            :      *      - an address where a contract lived, but was destroyed
+     249                 :            :      * @param _token L1 address of ERC20
+     250                 :            :      * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2
+     251                 :            :      * @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
+     252                 :            :                   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
+     253                 :            :      * @param _amount Token Amount
+     254                 :            :      * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution
+     255                 :            :      * @param _gasPriceBid Gas price for L2 execution
+     256                 :            :      * @param _data encoded data from router and user
+     257                 :            :      * @return res abi encoded inbox sequence number
+     258                 :            :      */
+     259                 :            :     function outboundTransferCustomRefund(
+     260                 :            :         address _token,
+     261                 :            :         address _refundTo,
+     262                 :            :         address _to,
+     263                 :            :         uint256 _amount,
+     264                 :            :         uint256 _maxGas,
+     265                 :            :         uint256 _gasPriceBid,
+     266                 :            :         bytes calldata _data
+     267                 :            :     ) public payable override returns (bytes memory) {
+     268                 :          0 :         address gateway = getGateway(_token);
+     269                 :          0 :         bytes memory gatewayData = GatewayMessageHandler.encodeFromRouterToGateway(
+     270                 :            :             msg.sender,
+     271                 :            :             _data
+     272                 :            :         );
+     273                 :            : 
+     274                 :          0 :         emit TransferRouted(_token, msg.sender, _to, gateway);
+     275                 :            :         // here we use `IL1ArbitrumGateway` since we don't assume all ITokenGateway implements `outboundTransferCustomRefund`
+     276                 :          0 :         return
+     277                 :            :             IL1ArbitrumGateway(gateway).outboundTransferCustomRefund{ value: msg.value }(
+     278                 :            :                 _token,
+     279                 :            :                 _refundTo,
+     280                 :            :                 _to,
+     281                 :            :                 _amount,
+     282                 :            :                 _maxGas,
+     283                 :            :                 _gasPriceBid,
+     284                 :            :                 gatewayData
+     285                 :            :             );
+     286                 :            :     }
+     287                 :            : 
+     288                 :            :     modifier onlyCounterpartGateway() override {
+     289                 :            :         // don't expect messages from L2 router
+     290                 :            :         revert("ONLY_COUNTERPART_GATEWAY");
+     291                 :            :         _;
+     292                 :            :     }
+     293                 :            : 
+     294                 :            :     function supportsInterface(bytes4 interfaceId)
+     295                 :            :         public
+     296                 :            :         view
+     297                 :            :         override(ERC165, IERC165)
+     298                 :            :         returns (bool)
+     299                 :            :     {
+     300                 :            :         // registering interfaces that is added after arb-bridge-peripherals >1.0.11
+     301                 :            :         // using function selector instead of single function interfaces to reduce bloat
+     302                 :        256 :         return
+     303                 :            :             interfaceId == this.outboundTransferCustomRefund.selector ||
+     304                 :            :             super.supportsInterface(interfaceId);
+     305                 :            :     }
+     306                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func-sort-c.html new file mode 100644 index 0000000000..95a53a384b --- /dev/null +++ b/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func-sort-c.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1OrbitERC20Gateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1OrbitERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:33100.0 %
Date:2023-04-27 16:26:32Functions:33100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1OrbitERC20Gateway._createRetryable2
L1OrbitERC20Gateway._initiateDeposit2
L1OrbitERC20Gateway._parseUserEncodedData5
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func.html b/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func.html new file mode 100644 index 0000000000..dd31b64e10 --- /dev/null +++ b/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1OrbitERC20Gateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1OrbitERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:33100.0 %
Date:2023-04-27 16:26:32Functions:33100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1OrbitERC20Gateway._createRetryable2
L1OrbitERC20Gateway._initiateDeposit2
L1OrbitERC20Gateway._parseUserEncodedData5
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.gcov.html b/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.gcov.html new file mode 100644 index 0000000000..e744dc123e --- /dev/null +++ b/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.gcov.html @@ -0,0 +1,166 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1OrbitERC20Gateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1OrbitERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:33100.0 %
Date:2023-04-27 16:26:32Functions:33100.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.0;
+       4                 :            : 
+       5                 :            : import "./L1ERC20Gateway.sol";
+       6                 :            : import { IERC20Inbox } from "../L1ArbitrumMessenger.sol";
+       7                 :            : 
+       8                 :            : /**
+       9                 :            :  * @title Layer 1 Gateway contract for bridging standard ERC20s in ERC20-based rollup
+      10                 :            :  * @notice This contract handles token deposits, holds the escrowed tokens on layer 1, and (ultimately) finalizes withdrawals.
+      11                 :            :  * @dev Any ERC20 that requires non-standard functionality should use a separate gateway.
+      12                 :            :  * Messages to layer 2 use the inbox's createRetryableTicket method.
+      13                 :            :  */
+      14                 :            : contract L1OrbitERC20Gateway is L1ERC20Gateway {
+      15                 :            :     function _parseUserEncodedData(
+      16                 :            :         bytes memory data
+      17                 :            :     )
+      18                 :            :         internal
+      19                 :            :         pure
+      20                 :            :         override
+      21                 :            :         returns (uint256 maxSubmissionCost, bytes memory callHookData, uint256 tokenTotalFeeAmount)
+      22                 :            :     {
+      23                 :          5 :         (maxSubmissionCost, callHookData, tokenTotalFeeAmount) = abi.decode(
+      24                 :            :             data,
+      25                 :            :             (uint256, bytes, uint256)
+      26                 :            :         );
+      27                 :            :     }
+      28                 :            : 
+      29                 :            :     function _initiateDeposit(
+      30                 :            :         address _refundTo,
+      31                 :            :         address _from,
+      32                 :            :         uint256,
+      33                 :            :         uint256 _maxGas,
+      34                 :            :         uint256 _gasPriceBid,
+      35                 :            :         uint256 _maxSubmissionCost,
+      36                 :            :         uint256 tokenTotalFeeAmount,
+      37                 :            :         bytes memory _data
+      38                 :            :     ) internal override returns (uint256) {
+      39                 :          2 :         return
+      40                 :            :             sendTxToL2CustomRefund(
+      41                 :            :                 inbox,
+      42                 :            :                 counterpartGateway,
+      43                 :            :                 _refundTo,
+      44                 :            :                 _from,
+      45                 :            :                 tokenTotalFeeAmount,
+      46                 :            :                 0,
+      47                 :            :                 L2GasParams({
+      48                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
+      49                 :            :                     _maxGas: _maxGas,
+      50                 :            :                     _gasPriceBid: _gasPriceBid
+      51                 :            :                 }),
+      52                 :            :                 _data
+      53                 :            :             );
+      54                 :            :     }
+      55                 :            : 
+      56                 :            :     function _createRetryable(
+      57                 :            :         address _inbox,
+      58                 :            :         address _to,
+      59                 :            :         address _refundTo,
+      60                 :            :         address _user,
+      61                 :            :         uint256 _totalFeeAmount,
+      62                 :            :         uint256 _l2CallValue,
+      63                 :            :         uint256 _maxSubmissionCost,
+      64                 :            :         uint256 _maxGas,
+      65                 :            :         uint256 _gasPriceBid,
+      66                 :            :         bytes memory _data
+      67                 :            :     ) internal override returns (uint256) {
+      68                 :          2 :         return
+      69                 :            :             IERC20Inbox(_inbox).createRetryableTicket(
+      70                 :            :                 _to,
+      71                 :            :                 _l2CallValue,
+      72                 :            :                 _maxSubmissionCost,
+      73                 :            :                 _refundTo,
+      74                 :            :                 _user,
+      75                 :            :                 _maxGas,
+      76                 :            :                 _gasPriceBid,
+      77                 :            :                 _totalFeeAmount,
+      78                 :            :                 _data
+      79                 :            :             );
+      80                 :            :     }
+      81                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..d1adb2d646 --- /dev/null +++ b/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ReverseCustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ReverseCustomGateway.inboundEscrowTransfer0
L1ReverseCustomGateway.outboundEscrowTransfer0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func.html b/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func.html new file mode 100644 index 0000000000..8e4312e9af --- /dev/null +++ b/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ReverseCustomGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1ReverseCustomGateway.inboundEscrowTransfer0
L1ReverseCustomGateway.outboundEscrowTransfer0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.gcov.html b/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.gcov.html new file mode 100644 index 0000000000..dd70a984d6 --- /dev/null +++ b/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.gcov.html @@ -0,0 +1,140 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1ReverseCustomGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./L1CustomGateway.sol";
+      22                 :            : import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+      23                 :            : 
+      24                 :            : /**
+      25                 :            :  * @title   L1 Gateway for reverse "custom" bridging functionality
+      26                 :            :  * @notice  Handles some (but not all!) reverse custom Gateway needs.
+      27                 :            :  *          Use the reverse custom gateway instead of the normal custom
+      28                 :            :  *          gateway if you want total supply to be tracked on the L2
+      29                 :            :  *          rather than the L1.
+      30                 :            :  * @dev     The reverse custom gateway burns on the l2 and escrows on the l1
+      31                 :            :  *          which is the opposite of the way the normal custom gateway works
+      32                 :            :  *          This means that the total supply L2 isn't affected by briding, which
+      33                 :            :  *          is helpful for observers calculating the total supply especially if
+      34                 :            :  *          if minting is also occuring on L2
+      35                 :            :  */
+      36                 :            : contract L1ReverseCustomGateway is L1CustomGateway {
+      37                 :            :     function inboundEscrowTransfer(
+      38                 :            :         address _l1Address,
+      39                 :            :         address _dest,
+      40                 :            :         uint256 _amount
+      41                 :            :     ) internal virtual override {
+      42                 :          0 :         IArbToken(_l1Address).bridgeMint(_dest, _amount);
+      43                 :            :     }
+      44                 :            : 
+      45                 :            :     function outboundEscrowTransfer(
+      46                 :            :         address _l1Token,
+      47                 :            :         address _from,
+      48                 :            :         uint256 _amount
+      49                 :            :     ) internal override returns (uint256) {
+      50                 :          0 :         IArbToken(_l1Token).bridgeBurn(_from, _amount);
+      51                 :            :         // by default we assume that the amount we send to bridgeBurn is the amount burnt
+      52                 :            :         // this might not be the case for every token
+      53                 :          0 :         return _amount;
+      54                 :            :     }
+      55                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1WethGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1WethGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..e9b62d29ac --- /dev/null +++ b/coverage/ethereum/gateway/L1WethGateway.sol.func-sort-c.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1WethGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0150.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1WethGateway.calculateL2TokenAddress0
L1WethGateway.createOutboundTxCustomRefund0
L1WethGateway.inboundEscrowTransfer0
L1WethGateway.initialize0
L1WethGateway.outboundEscrowTransfer0
L1WethGateway.setRedirectedExit0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1WethGateway.sol.func.html b/coverage/ethereum/gateway/L1WethGateway.sol.func.html new file mode 100644 index 0000000000..f1a1333fd0 --- /dev/null +++ b/coverage/ethereum/gateway/L1WethGateway.sol.func.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1WethGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0150.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L1WethGateway.calculateL2TokenAddress0
L1WethGateway.createOutboundTxCustomRefund0
L1WethGateway.inboundEscrowTransfer0
L1WethGateway.initialize0
L1WethGateway.outboundEscrowTransfer0
L1WethGateway.setRedirectedExit0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/L1WethGateway.sol.gcov.html b/coverage/ethereum/gateway/L1WethGateway.sol.gcov.html new file mode 100644 index 0000000000..7379cf26ff --- /dev/null +++ b/coverage/ethereum/gateway/L1WethGateway.sol.gcov.html @@ -0,0 +1,210 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway/L1WethGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gateway - L1WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0150.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:060.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "@arbitrum/nitro-contracts/src/bridge/IInbox.sol";
+      22                 :            : import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
+      23                 :            : import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+      24                 :            : import "../../libraries/IWETH9.sol";
+      25                 :            : import "../../test/TestWETH9.sol";
+      26                 :            : import "./L1ArbitrumExtendedGateway.sol";
+      27                 :            : 
+      28                 :            : contract L1WethGateway is L1ArbitrumExtendedGateway {
+      29                 :            :     using SafeERC20 for IERC20;
+      30                 :            : 
+      31                 :            :     address public l1Weth;
+      32                 :            :     address public l2Weth;
+      33                 :            : 
+      34                 :            :     function initialize(
+      35                 :            :         address _l2Counterpart,
+      36                 :            :         address _l1Router,
+      37                 :            :         address _inbox,
+      38                 :            :         address _l1Weth,
+      39                 :            :         address _l2Weth
+      40                 :            :     ) public {
+      41                 :          0 :         L1ArbitrumGateway._initialize(_l2Counterpart, _l1Router, _inbox);
+      42         [ #  # ]:          0 :         require(_l1Weth != address(0), "INVALID_L1WETH");
+      43         [ #  # ]:          0 :         require(_l2Weth != address(0), "INVALID_L2WETH");
+      44                 :          0 :         l1Weth = _l1Weth;
+      45                 :          0 :         l2Weth = _l2Weth;
+      46                 :            :     }
+      47                 :            : 
+      48                 :            :     function createOutboundTxCustomRefund(
+      49                 :            :         address _refundTo,
+      50                 :            :         address _from,
+      51                 :            :         uint256 _tokenAmount,
+      52                 :            :         uint256 _maxGas,
+      53                 :            :         uint256 _gasPriceBid,
+      54                 :            :         uint256 _maxSubmissionCost,
+      55                 :            :         bytes memory _outboundCalldata
+      56                 :            :     ) internal override returns (uint256) {
+      57                 :          0 :         return
+      58                 :            :             sendTxToL2CustomRefund(
+      59                 :            :                 inbox,
+      60                 :            :                 counterpartGateway,
+      61                 :            :                 _refundTo,
+      62                 :            :                 _from,
+      63                 :            :                 // msg.value does not include weth withdrawn from user, we need to add in that amount
+      64                 :            :                 msg.value + _tokenAmount,
+      65                 :            :                 // send token amount to L2 as call value
+      66                 :            :                 _tokenAmount,
+      67                 :            :                 L2GasParams({
+      68                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
+      69                 :            :                     _maxGas: _maxGas,
+      70                 :            :                     _gasPriceBid: _gasPriceBid
+      71                 :            :                 }),
+      72                 :            :                 _outboundCalldata
+      73                 :            :             );
+      74                 :            :     }
+      75                 :            : 
+      76                 :            :     function outboundEscrowTransfer(
+      77                 :            :         address _l1Token,
+      78                 :            :         address _from,
+      79                 :            :         uint256 _amount
+      80                 :            :     ) internal override returns (uint256) {
+      81                 :          0 :         IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);
+      82                 :          0 :         IWETH9(_l1Token).withdraw(_amount);
+      83                 :            :         // the weth token doesn't contain any special behaviour that changes the amount
+      84                 :            :         // when doing transfers / withdrawals. so we don't check the balanceOf
+      85                 :          0 :         return _amount;
+      86                 :            :     }
+      87                 :            : 
+      88                 :            :     function inboundEscrowTransfer(
+      89                 :            :         address _l1Token,
+      90                 :            :         address _dest,
+      91                 :            :         uint256 _amount
+      92                 :            :     ) internal override {
+      93                 :          0 :         IWETH9(_l1Token).deposit{ value: _amount }();
+      94                 :          0 :         IERC20(_l1Token).safeTransfer(_dest, _amount);
+      95                 :            :     }
+      96                 :            : 
+      97                 :            :     /**
+      98                 :            :      * @notice Calculate the address used when bridging an ERC20 token
+      99                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
+     100                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
+     101                 :            :      * @param l1ERC20 address of L1 token
+     102                 :            :      * @return L2 address of a bridged ERC20 token
+     103                 :            :      */
+     104                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override(ITokenGateway, TokenGateway) returns (address) {
+     105         [ #  # ]:          0 :         if (l1ERC20 != l1Weth) {
+     106                 :            :             // invalid L1 weth address
+     107                 :          0 :             return address(0);
+     108                 :            :         }
+     109                 :          0 :         return l2Weth;
+     110                 :            :     }
+     111                 :            : 
+     112                 :            :     /**
+     113                 :            :      * @notice  Temporary disable the ability to trade exits
+     114                 :            :      */
+     115                 :            :     function setRedirectedExit(
+     116                 :            :         uint256 _exitNum,
+     117                 :            :         address _initialDestination,
+     118                 :            :         address _newDestination,
+     119                 :            :         bytes memory _newData
+     120                 :            :     ) internal override {
+     121                 :          0 :         revert("TRADABLE_EXIT_TEMP_DISABLED");
+     122                 :            :     }
+     123                 :            : 
+     124                 :            :     receive() external payable {}
+     125                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/index-sort-b.html b/coverage/ethereum/gateway/index-sort-b.html new file mode 100644 index 0000000000..70dd8915ea --- /dev/null +++ b/coverage/ethereum/gateway/index-sort-b.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gatewayHitTotalCoverage
Test:lcov.infoLines:12817374.0 %
Date:2023-04-27 16:26:32Functions:355366.0 %
Branches:406858.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1WethGateway.sol +
0.0%
+
0.0 %0 / 150.0 %0 / 60.0 %0 / 6
L1CustomGateway.sol +
57.1%57.1%
+
57.1 %16 / 2842.9 %3 / 710.0 %1 / 10
L1ArbitrumGateway.sol +
81.2%81.2%
+
81.2 %39 / 4878.6 %11 / 1466.7 %12 / 18
L1GatewayRouter.sol +
87.5%87.5%
+
87.5 %35 / 4077.8 %7 / 972.2 %13 / 18
L1ArbitrumExtendedGateway.sol +
100.0%
+
100.0 %17 / 17100.0 %4 / 483.3 %10 / 12
L1OrbitERC20Gateway.sol +
100.0%
+
100.0 %3 / 3100.0 %3 / 3-0 / 0
L1ForceOnlyReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
L1ReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 2-0 / 0
L1ERC20Gateway.sol +
100.0%
+
100.0 %18 / 18100.0 %7 / 7100.0 %4 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/index-sort-f.html b/coverage/ethereum/gateway/index-sort-f.html new file mode 100644 index 0000000000..90cce7812f --- /dev/null +++ b/coverage/ethereum/gateway/index-sort-f.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gatewayHitTotalCoverage
Test:lcov.infoLines:12817374.0 %
Date:2023-04-27 16:26:32Functions:355366.0 %
Branches:406858.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ForceOnlyReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
L1ReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 2-0 / 0
L1WethGateway.sol +
0.0%
+
0.0 %0 / 150.0 %0 / 60.0 %0 / 6
L1CustomGateway.sol +
57.1%57.1%
+
57.1 %16 / 2842.9 %3 / 710.0 %1 / 10
L1GatewayRouter.sol +
87.5%87.5%
+
87.5 %35 / 4077.8 %7 / 972.2 %13 / 18
L1ArbitrumGateway.sol +
81.2%81.2%
+
81.2 %39 / 4878.6 %11 / 1466.7 %12 / 18
L1OrbitERC20Gateway.sol +
100.0%
+
100.0 %3 / 3100.0 %3 / 3-0 / 0
L1ArbitrumExtendedGateway.sol +
100.0%
+
100.0 %17 / 17100.0 %4 / 483.3 %10 / 12
L1ERC20Gateway.sol +
100.0%
+
100.0 %18 / 18100.0 %7 / 7100.0 %4 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/index-sort-l.html b/coverage/ethereum/gateway/index-sort-l.html new file mode 100644 index 0000000000..da8eca2e37 --- /dev/null +++ b/coverage/ethereum/gateway/index-sort-l.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gatewayHitTotalCoverage
Test:lcov.infoLines:12817374.0 %
Date:2023-04-27 16:26:32Functions:355366.0 %
Branches:406858.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ForceOnlyReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
L1ReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 2-0 / 0
L1WethGateway.sol +
0.0%
+
0.0 %0 / 150.0 %0 / 60.0 %0 / 6
L1CustomGateway.sol +
57.1%57.1%
+
57.1 %16 / 2842.9 %3 / 710.0 %1 / 10
L1ArbitrumGateway.sol +
81.2%81.2%
+
81.2 %39 / 4878.6 %11 / 1466.7 %12 / 18
L1GatewayRouter.sol +
87.5%87.5%
+
87.5 %35 / 4077.8 %7 / 972.2 %13 / 18
L1OrbitERC20Gateway.sol +
100.0%
+
100.0 %3 / 3100.0 %3 / 3-0 / 0
L1ArbitrumExtendedGateway.sol +
100.0%
+
100.0 %17 / 17100.0 %4 / 483.3 %10 / 12
L1ERC20Gateway.sol +
100.0%
+
100.0 %18 / 18100.0 %7 / 7100.0 %4 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/gateway/index.html b/coverage/ethereum/gateway/index.html new file mode 100644 index 0000000000..35ad39b6a7 --- /dev/null +++ b/coverage/ethereum/gateway/index.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - lcov.info - ethereum/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereum/gatewayHitTotalCoverage
Test:lcov.infoLines:12817374.0 %
Date:2023-04-27 16:26:32Functions:355366.0 %
Branches:406858.8 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.sol +
100.0%
+
100.0 %17 / 17100.0 %4 / 483.3 %10 / 12
L1ArbitrumGateway.sol +
81.2%81.2%
+
81.2 %39 / 4878.6 %11 / 1466.7 %12 / 18
L1CustomGateway.sol +
57.1%57.1%
+
57.1 %16 / 2842.9 %3 / 710.0 %1 / 10
L1ERC20Gateway.sol +
100.0%
+
100.0 %18 / 18100.0 %7 / 7100.0 %4 / 4
L1ForceOnlyReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
L1GatewayRouter.sol +
87.5%87.5%
+
87.5 %35 / 4077.8 %7 / 972.2 %13 / 18
L1OrbitERC20Gateway.sol +
100.0%
+
100.0 %3 / 3100.0 %3 / 3-0 / 0
L1ReverseCustomGateway.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 2-0 / 0
L1WethGateway.sol +
0.0%
+
0.0 %0 / 150.0 %0 / 60.0 %0 / 6
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/index-sort-b.html b/coverage/ethereum/index-sort-b.html new file mode 100644 index 0000000000..69c3172fee --- /dev/null +++ b/coverage/ethereum/index-sort-b.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - ethereum + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereumHitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumMessenger.sol +
100.0%
+
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/index-sort-f.html b/coverage/ethereum/index-sort-f.html new file mode 100644 index 0000000000..1c00fa4037 --- /dev/null +++ b/coverage/ethereum/index-sort-f.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - ethereum + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereumHitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumMessenger.sol +
100.0%
+
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/index-sort-l.html b/coverage/ethereum/index-sort-l.html new file mode 100644 index 0000000000..3947fd0349 --- /dev/null +++ b/coverage/ethereum/index-sort-l.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - ethereum + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereumHitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumMessenger.sol +
100.0%
+
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ethereum/index.html b/coverage/ethereum/index.html new file mode 100644 index 0000000000..78fa0bfb1e --- /dev/null +++ b/coverage/ethereum/index.html @@ -0,0 +1,107 @@ + + + + + + + LCOV - lcov.info - ethereum + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - ethereumHitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumMessenger.sol +
100.0%
+
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/gcov.css b/coverage/gcov.css new file mode 100644 index 0000000000..0fcdff13ce --- /dev/null +++ b/coverage/gcov.css @@ -0,0 +1,519 @@ +/* All views: initial background and text color */ +body +{ + color: #000000; + background-color: #ffffff; +} + +/* All views: standard link format*/ +a:link +{ + color: #284fa8; + text-decoration: underline; +} + +/* All views: standard link - visited format */ +a:visited +{ + color: #00cb40; + text-decoration: underline; +} + +/* All views: standard link - activated format */ +a:active +{ + color: #ff0040; + text-decoration: underline; +} + +/* All views: main title format */ +td.title +{ + text-align: center; + padding-bottom: 10px; + font-family: sans-serif; + font-size: 20pt; + font-style: italic; + font-weight: bold; +} + +/* All views: header item format */ +td.headerItem +{ + text-align: right; + padding-right: 6px; + font-family: sans-serif; + font-weight: bold; + vertical-align: top; + white-space: nowrap; +} + +/* All views: header item value format */ +td.headerValue +{ + text-align: left; + color: #284fa8; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; +} + +/* All views: header item coverage table heading */ +td.headerCovTableHead +{ + text-align: center; + padding-right: 6px; + padding-left: 6px; + padding-bottom: 0px; + font-family: sans-serif; + font-size: 80%; + white-space: nowrap; +} + +/* All views: header item coverage table entry */ +td.headerCovTableEntry +{ + text-align: right; + color: #284fa8; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #dae7fe; +} + +/* All views: header item coverage table entry for high coverage rate */ +td.headerCovTableEntryHi +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #a7fc9d; +} + +/* All views: header item coverage table entry for medium coverage rate */ +td.headerCovTableEntryMed +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #ffea20; +} + +/* All views: header item coverage table entry for ow coverage rate */ +td.headerCovTableEntryLo +{ + text-align: right; + color: #000000; + font-family: sans-serif; + font-weight: bold; + white-space: nowrap; + padding-left: 12px; + padding-right: 4px; + background-color: #ff0000; +} + +/* All views: header legend value for legend entry */ +td.headerValueLeg +{ + text-align: left; + color: #000000; + font-family: sans-serif; + font-size: 80%; + white-space: nowrap; + padding-top: 4px; +} + +/* All views: color of horizontal ruler */ +td.ruler +{ + background-color: #6688d4; +} + +/* All views: version string format */ +td.versionInfo +{ + text-align: center; + padding-top: 2px; + font-family: sans-serif; + font-style: italic; +} + +/* Directory view/File view (all)/Test case descriptions: + table headline format */ +td.tableHead +{ + text-align: center; + color: #ffffff; + background-color: #6688d4; + font-family: sans-serif; + font-size: 120%; + font-weight: bold; + white-space: nowrap; + padding-left: 4px; + padding-right: 4px; +} + +span.tableHeadSort +{ + padding-right: 4px; +} + +/* Directory view/File view (all): filename entry format */ +td.coverFile +{ + text-align: left; + padding-left: 10px; + padding-right: 20px; + color: #284fa8; + background-color: #dae7fe; + font-family: monospace; +} + +/* Directory view/File view (all): bar-graph entry format*/ +td.coverBar +{ + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; +} + +/* Directory view/File view (all): bar-graph outline color */ +td.coverBarOutline +{ + background-color: #000000; +} + +/* Directory view/File view (all): percentage entry for files with + high coverage rate */ +td.coverPerHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #a7fc9d; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + high coverage rate */ +td.coverNumHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #a7fc9d; + white-space: nowrap; + font-family: sans-serif; +} + +/* Directory view/File view (all): percentage entry for files with + medium coverage rate */ +td.coverPerMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ffea20; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + medium coverage rate */ +td.coverNumMed +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ffea20; + white-space: nowrap; + font-family: sans-serif; +} + +/* Directory view/File view (all): percentage entry for files with + low coverage rate */ +td.coverPerLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ff0000; + font-weight: bold; + font-family: sans-serif; +} + +/* Directory view/File view (all): line count entry for files with + low coverage rate */ +td.coverNumLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ff0000; + white-space: nowrap; + font-family: sans-serif; +} + +/* File view (all): "show/hide details" link format */ +a.detail:link +{ + color: #B8D0FF; + font-size:80%; +} + +/* File view (all): "show/hide details" link - visited format */ +a.detail:visited +{ + color: #B8D0FF; + font-size:80%; +} + +/* File view (all): "show/hide details" link - activated format */ +a.detail:active +{ + color: #ffffff; + font-size:80%; +} + +/* File view (detail): test name entry */ +td.testName +{ + text-align: right; + padding-right: 10px; + background-color: #dae7fe; + font-family: sans-serif; +} + +/* File view (detail): test percentage entry */ +td.testPer +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-family: sans-serif; +} + +/* File view (detail): test lines count entry */ +td.testNum +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-family: sans-serif; +} + +/* Test case descriptions: test name format*/ +dt +{ + font-family: sans-serif; + font-weight: bold; +} + +/* Test case descriptions: description table body */ +td.testDescription +{ + padding-top: 10px; + padding-left: 30px; + padding-bottom: 10px; + padding-right: 30px; + background-color: #dae7fe; +} + +/* Source code view: function entry */ +td.coverFn +{ + text-align: left; + padding-left: 10px; + padding-right: 20px; + color: #284fa8; + background-color: #dae7fe; + font-family: monospace; +} + +/* Source code view: function entry zero count*/ +td.coverFnLo +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #ff0000; + font-weight: bold; + font-family: sans-serif; +} + +/* Source code view: function entry nonzero count*/ +td.coverFnHi +{ + text-align: right; + padding-left: 10px; + padding-right: 10px; + background-color: #dae7fe; + font-weight: bold; + font-family: sans-serif; +} + +/* Source code view: source code format */ +pre.source +{ + font-family: monospace; + white-space: pre; + margin-top: 2px; +} + +/* Source code view: line number format */ +span.lineNum +{ + background-color: #efe383; +} + +/* Source code view: format for lines which were executed */ +td.lineCov, +span.lineCov +{ + background-color: #cad7fe; +} + +/* Source code view: format for Cov legend */ +span.coverLegendCov +{ + padding-left: 10px; + padding-right: 10px; + padding-bottom: 2px; + background-color: #cad7fe; +} + +/* Source code view: format for lines which were not executed */ +td.lineNoCov, +span.lineNoCov +{ + background-color: #ff6230; +} + +/* Source code view: format for NoCov legend */ +span.coverLegendNoCov +{ + padding-left: 10px; + padding-right: 10px; + padding-bottom: 2px; + background-color: #ff6230; +} + +/* Source code view (function table): standard link - visited format */ +td.lineNoCov > a:visited, +td.lineCov > a:visited +{ + color: #000000; + text-decoration: underline; +} + +/* Source code view: format for lines which were executed only in a + previous version */ +span.lineDiffCov +{ + background-color: #b5f7af; +} + +/* Source code view: format for branches which were executed + * and taken */ +span.branchCov +{ + background-color: #cad7fe; +} + +/* Source code view: format for branches which were executed + * but not taken */ +span.branchNoCov +{ + background-color: #ff6230; +} + +/* Source code view: format for branches which were not executed */ +span.branchNoExec +{ + background-color: #ff6230; +} + +/* Source code view: format for the source code heading line */ +pre.sourceHeading +{ + white-space: pre; + font-family: monospace; + font-weight: bold; + margin: 0px; +} + +/* All views: header legend value for low rate */ +td.headerValueLegL +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 4px; + padding-right: 2px; + background-color: #ff0000; + font-size: 80%; +} + +/* All views: header legend value for med rate */ +td.headerValueLegM +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 2px; + padding-right: 2px; + background-color: #ffea20; + font-size: 80%; +} + +/* All views: header legend value for hi rate */ +td.headerValueLegH +{ + font-family: sans-serif; + text-align: center; + white-space: nowrap; + padding-left: 2px; + padding-right: 4px; + background-color: #a7fc9d; + font-size: 80%; +} + +/* All views except source code view: legend format for low coverage */ +span.coverLegendCovLo +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #ff0000; +} + +/* All views except source code view: legend format for med coverage */ +span.coverLegendCovMed +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #ffea20; +} + +/* All views except source code view: legend format for hi coverage */ +span.coverLegendCovHi +{ + padding-left: 10px; + padding-right: 10px; + padding-top: 2px; + background-color: #a7fc9d; +} diff --git a/coverage/glass.png b/coverage/glass.png new file mode 100644 index 0000000000000000000000000000000000000000..e1abc00680a3093c49fdb775ae6bdb6764c95af2 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)gaEa{HEjtmSN`?>!lvI6;R0X`wF z|Ns97GD8ntt^-nxB|(0{3=Yq3q=7g|-tI089jvk*Kn`btM`SSr1Gf+eGhVt|_XjA* zUgGKN%6^Gmn4d%Ph(nkFP>9RZ#WAE}PI3Z}&BVayv3^M*kj3EX>gTe~DWM4f=_Dpv literal 0 HcmV?d00001 diff --git a/coverage/index-sort-b.html b/coverage/index-sort-b.html new file mode 100644 index 0000000000..c244bb0320 --- /dev/null +++ b/coverage/index-sort-b.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:21163533.2 %
Date:2023-04-27 16:26:32Functions:6623628.0 %
Branches:6322627.9 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
arbitrum +
0.0%
+
0.0 %0 / 170.0 %0 / 70.0 %0 / 6
/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils +
0.0%
+
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
arbitrum/gateway +
0.0%
+
0.0 %0 / 980.0 %0 / 290.0 %0 / 38
test +
22.4%22.4%
+
22.4 %15 / 6718.9 %7 / 3714.3 %2 / 14
libraries +
22.9%22.9%
+
22.9 %39 / 17022.6 %14 / 6215.6 %10 / 64
ethereum +
100.0%
+
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
ethereum/gateway +
74.0%74.0%
+
74.0 %128 / 17366.0 %35 / 5358.8 %40 / 68
libraries/gateway +
45.5%45.5%
+
45.5 %15 / 3326.7 %4 / 1571.4 %10 / 14
/Users/goran/repos/offchain/token-bridge-contracts/test-foundry +
100.0%
+
100.0 %2 / 2100.0 %1 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/index-sort-f.html b/coverage/index-sort-f.html new file mode 100644 index 0000000000..11471f8a22 --- /dev/null +++ b/coverage/index-sort-f.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:21163533.2 %
Date:2023-04-27 16:26:32Functions:6623628.0 %
Branches:6322627.9 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
arbitrum +
0.0%
+
0.0 %0 / 170.0 %0 / 70.0 %0 / 6
/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils +
0.0%
+
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
arbitrum/gateway +
0.0%
+
0.0 %0 / 980.0 %0 / 290.0 %0 / 38
test +
22.4%22.4%
+
22.4 %15 / 6718.9 %7 / 3714.3 %2 / 14
libraries +
22.9%22.9%
+
22.9 %39 / 17022.6 %14 / 6215.6 %10 / 64
libraries/gateway +
45.5%45.5%
+
45.5 %15 / 3326.7 %4 / 1571.4 %10 / 14
ethereum/gateway +
74.0%74.0%
+
74.0 %128 / 17366.0 %35 / 5358.8 %40 / 68
/Users/goran/repos/offchain/token-bridge-contracts/test-foundry +
100.0%
+
100.0 %2 / 2100.0 %1 / 1-0 / 0
ethereum +
100.0%
+
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/index-sort-l.html b/coverage/index-sort-l.html new file mode 100644 index 0000000000..192d3c52be --- /dev/null +++ b/coverage/index-sort-l.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:21163533.2 %
Date:2023-04-27 16:26:32Functions:6623628.0 %
Branches:6322627.9 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
arbitrum +
0.0%
+
0.0 %0 / 170.0 %0 / 70.0 %0 / 6
/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils +
0.0%
+
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
arbitrum/gateway +
0.0%
+
0.0 %0 / 980.0 %0 / 290.0 %0 / 38
test +
22.4%22.4%
+
22.4 %15 / 6718.9 %7 / 3714.3 %2 / 14
libraries +
22.9%22.9%
+
22.9 %39 / 17022.6 %14 / 6215.6 %10 / 64
libraries/gateway +
45.5%45.5%
+
45.5 %15 / 3326.7 %4 / 1571.4 %10 / 14
ethereum/gateway +
74.0%74.0%
+
74.0 %128 / 17366.0 %35 / 5358.8 %40 / 68
/Users/goran/repos/offchain/token-bridge-contracts/test-foundry +
100.0%
+
100.0 %2 / 2100.0 %1 / 1-0 / 0
ethereum +
100.0%
+
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/index.html b/coverage/index.html new file mode 100644 index 0000000000..646fd861a2 --- /dev/null +++ b/coverage/index.html @@ -0,0 +1,203 @@ + + + + + + + LCOV - lcov.info + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:21163533.2 %
Date:2023-04-27 16:26:32Functions:6623628.0 %
Branches:6322627.9 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils +
0.0%
+
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
/Users/goran/repos/offchain/token-bridge-contracts/test-foundry +
100.0%
+
100.0 %2 / 2100.0 %1 / 1-0 / 0
arbitrum +
0.0%
+
0.0 %0 / 170.0 %0 / 70.0 %0 / 6
arbitrum/gateway +
0.0%
+
0.0 %0 / 980.0 %0 / 290.0 %0 / 38
ethereum +
100.0%
+
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
ethereum/gateway +
74.0%74.0%
+
74.0 %128 / 17366.0 %35 / 5358.8 %40 / 68
libraries +
22.9%22.9%
+
22.9 %39 / 17022.6 %14 / 6215.6 %10 / 64
libraries/gateway +
45.5%45.5%
+
45.5 %15 / 3326.7 %4 / 1571.4 %10 / 14
test +
22.4%22.4%
+
22.4 %15 / 6718.9 %7 / 3714.3 %2 / 14
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/AddressAliasHelper.sol.func-sort-c.html b/coverage/libraries/AddressAliasHelper.sol.func-sort-c.html new file mode 100644 index 0000000000..342e092c2d --- /dev/null +++ b/coverage/libraries/AddressAliasHelper.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - libraries/AddressAliasHelper.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - AddressAliasHelper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
AddressAliasHelper.applyL1ToL2Alias0
AddressAliasHelper.undoL1ToL2Alias0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/AddressAliasHelper.sol.func.html b/coverage/libraries/AddressAliasHelper.sol.func.html new file mode 100644 index 0000000000..b0faa2edd1 --- /dev/null +++ b/coverage/libraries/AddressAliasHelper.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - libraries/AddressAliasHelper.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - AddressAliasHelper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
AddressAliasHelper.applyL1ToL2Alias0
AddressAliasHelper.undoL1ToL2Alias0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/AddressAliasHelper.sol.gcov.html b/coverage/libraries/AddressAliasHelper.sol.gcov.html new file mode 100644 index 0000000000..5b87a4c4c3 --- /dev/null +++ b/coverage/libraries/AddressAliasHelper.sol.gcov.html @@ -0,0 +1,128 @@ + + + + + + + LCOV - lcov.info - libraries/AddressAliasHelper.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - AddressAliasHelper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2019-2021, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : library AddressAliasHelper {
+      22                 :            :     uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);
+      23                 :            : 
+      24                 :            :     /// @notice Utility function that converts the address in the L1 that submitted a tx to
+      25                 :            :     /// the inbox to the msg.sender viewed in the L2
+      26                 :            :     /// @param l1Address the address in the L1 that triggered the tx to L2
+      27                 :            :     /// @return l2Address L2 address as viewed in msg.sender
+      28                 :            :     function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {
+      29                 :            :         unchecked {
+      30                 :          0 :             l2Address = address(uint160(l1Address) + offset);
+      31                 :            :         }
+      32                 :            :     }
+      33                 :            : 
+      34                 :            :     /// @notice Utility function that converts the msg.sender viewed in the L2 to the
+      35                 :            :     /// address in the L1 that submitted a tx to the inbox
+      36                 :            :     /// @param l2Address L2 address as viewed in msg.sender
+      37                 :            :     /// @return l1Address the address in the L1 that triggered the tx to L2
+      38                 :            :     function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {
+      39                 :            :         unchecked {
+      40                 :          0 :             l1Address = address(uint160(l2Address) - offset);
+      41                 :            :         }
+      42                 :            :     }
+      43                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/BytesLib.sol.func-sort-c.html b/coverage/libraries/BytesLib.sol.func-sort-c.html new file mode 100644 index 0000000000..f8de1a1f9e --- /dev/null +++ b/coverage/libraries/BytesLib.sol.func-sort-c.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - libraries/BytesLib.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - BytesLib.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:080.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
BytesLib.toAddress0
BytesLib.toBytes320
BytesLib.toUint0
BytesLib.toUint80
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/BytesLib.sol.func.html b/coverage/libraries/BytesLib.sol.func.html new file mode 100644 index 0000000000..6ece999e67 --- /dev/null +++ b/coverage/libraries/BytesLib.sol.func.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - libraries/BytesLib.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - BytesLib.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:080.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
BytesLib.toAddress0
BytesLib.toBytes320
BytesLib.toUint0
BytesLib.toUint80
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/BytesLib.sol.gcov.html b/coverage/libraries/BytesLib.sol.gcov.html new file mode 100644 index 0000000000..8d4237f627 --- /dev/null +++ b/coverage/libraries/BytesLib.sol.gcov.html @@ -0,0 +1,144 @@ + + + + + + + LCOV - lcov.info - libraries/BytesLib.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - BytesLib.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:080.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MIT
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * @title Solidity Bytes Arrays Utils
+       5                 :            :  * @author Gonçalo Sá <goncalo.sa@consensys.net>
+       6                 :            :  *
+       7                 :            :  * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
+       8                 :            :  *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
+       9                 :            :  */
+      10                 :            : 
+      11                 :            : pragma solidity ^0.8.0;
+      12                 :            : 
+      13                 :            : /* solhint-disable no-inline-assembly */
+      14                 :            : library BytesLib {
+      15                 :            :     function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
+      16         [ #  # ]:          0 :         require(_bytes.length >= (_start + 20), "Read out of bounds");
+      17                 :          0 :         address tempAddress;
+      18                 :            : 
+      19                 :            :         assembly {
+      20                 :          0 :             tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
+      21                 :            :         }
+      22                 :            : 
+      23                 :          0 :         return tempAddress;
+      24                 :            :     }
+      25                 :            : 
+      26                 :            :     function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
+      27         [ #  # ]:          0 :         require(_bytes.length >= (_start + 1), "Read out of bounds");
+      28                 :          0 :         uint8 tempUint;
+      29                 :            : 
+      30                 :            :         assembly {
+      31                 :          0 :             tempUint := mload(add(add(_bytes, 0x1), _start))
+      32                 :            :         }
+      33                 :            : 
+      34                 :          0 :         return tempUint;
+      35                 :            :     }
+      36                 :            : 
+      37                 :            :     function toUint(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
+      38         [ #  # ]:          0 :         require(_bytes.length >= (_start + 32), "Read out of bounds");
+      39                 :          0 :         uint256 tempUint;
+      40                 :            : 
+      41                 :            :         assembly {
+      42                 :          0 :             tempUint := mload(add(add(_bytes, 0x20), _start))
+      43                 :            :         }
+      44                 :            : 
+      45                 :          0 :         return tempUint;
+      46                 :            :     }
+      47                 :            : 
+      48                 :            :     function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
+      49         [ #  # ]:          0 :         require(_bytes.length >= (_start + 32), "Read out of bounds");
+      50                 :          0 :         bytes32 tempBytes32;
+      51                 :            : 
+      52                 :            :         assembly {
+      53                 :          0 :             tempBytes32 := mload(add(add(_bytes, 0x20), _start))
+      54                 :            :         }
+      55                 :            : 
+      56                 :          0 :         return tempBytes32;
+      57                 :            :     }
+      58                 :            : }
+      59                 :            : /* solhint-enable no-inline-assembly */
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/BytesParser.sol.func-sort-c.html b/coverage/libraries/BytesParser.sol.func-sort-c.html new file mode 100644 index 0000000000..e308feaec2 --- /dev/null +++ b/coverage/libraries/BytesParser.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - libraries/BytesParser.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - BytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0210.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:0100.0 %
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
BytesParser.toString0
BytesParser.toUint80
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/BytesParser.sol.func.html b/coverage/libraries/BytesParser.sol.func.html new file mode 100644 index 0000000000..ab09f3d5d9 --- /dev/null +++ b/coverage/libraries/BytesParser.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - libraries/BytesParser.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - BytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0210.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:0100.0 %
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
BytesParser.toString0
BytesParser.toUint80
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/BytesParser.sol.gcov.html b/coverage/libraries/BytesParser.sol.gcov.html new file mode 100644 index 0000000000..c87cd97682 --- /dev/null +++ b/coverage/libraries/BytesParser.sol.gcov.html @@ -0,0 +1,156 @@ + + + + + + + LCOV - lcov.info - libraries/BytesParser.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - BytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0210.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:0100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./BytesLib.sol";
+      22                 :            : 
+      23                 :            : library BytesParser {
+      24                 :            :     using BytesLib for bytes;
+      25                 :            : 
+      26                 :            :     function toUint8(bytes memory input) internal pure returns (bool success, uint8 res) {
+      27         [ #  # ]:          0 :         if (input.length != 32) {
+      28                 :          0 :             return (false, 0);
+      29                 :            :         }
+      30                 :            :         // TODO: try catch to handle error
+      31                 :          0 :         uint256 inputNum = abi.decode(input, (uint256));
+      32         [ #  # ]:          0 :         if (inputNum > type(uint8).max) {
+      33                 :          0 :             return (false, 0);
+      34                 :            :         }
+      35                 :          0 :         res = uint8(inputNum);
+      36                 :          0 :         success = true;
+      37                 :            :     }
+      38                 :            : 
+      39                 :            :     function toString(bytes memory input) internal pure returns (bool success, string memory res) {
+      40         [ #  # ]:          0 :         if (input.length == 0) {
+      41                 :          0 :             success = false;
+      42                 :            :             // return default value of string
+      43         [ #  # ]:          0 :         } else if (input.length == 32) {
+      44                 :            :             // TODO: can validate anything other than length and being null terminated?
+      45         [ #  # ]:          0 :             if (input[31] != bytes1(0x00)) return (false, res);
+      46                 :          0 :             else success = true;
+      47                 :            : 
+      48                 :            :             // here we assume its a null terminated Bytes32 string
+      49                 :            :             // https://github.com/ethereum/solidity/blob/5852972ec148bc041909400affc778dee66d384d/test/libsolidity/semanticTests/externalContracts/_stringutils/stringutils.sol#L89
+      50                 :            :             // https://github.com/Arachnid/solidity-stringutils
+      51                 :          0 :             uint256 len = 32;
+      52                 :          0 :             while (len > 0 && input[len - 1] == bytes1(0x00)) {
+      53                 :          0 :                 len--;
+      54                 :            :             }
+      55                 :            : 
+      56                 :          0 :             bytes memory inputTruncated = new bytes(len);
+      57                 :          0 :             for (uint8 i = 0; i < len; i++) {
+      58                 :          0 :                 inputTruncated[i] = input[i];
+      59                 :            :             }
+      60                 :            :             // we can't just do `res := input` because of the null values in the end
+      61                 :            :             // TODO: can we instead use a bitwise AND? build it dynamically with the length
+      62                 :            :             assembly {
+      63                 :          0 :                 res := inputTruncated
+      64                 :            :             }
+      65                 :            :         } else {
+      66                 :            :             // TODO: try catch to handle error
+      67                 :          0 :             success = true;
+      68                 :          0 :             res = abi.decode(input, (string));
+      69                 :            :         }
+      70                 :            :     }
+      71                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ClonableBeaconProxy.sol.func-sort-c.html b/coverage/libraries/ClonableBeaconProxy.sol.func-sort-c.html new file mode 100644 index 0000000000..0c5732f7f1 --- /dev/null +++ b/coverage/libraries/ClonableBeaconProxy.sol.func-sort-c.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - libraries/ClonableBeaconProxy.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ClonableBeaconProxy.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
BeaconProxyFactory.calculateExpectedAddress0
BeaconProxyFactory.createProxy0
BeaconProxyFactory.getSalt0
BeaconProxyFactory.initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ClonableBeaconProxy.sol.func.html b/coverage/libraries/ClonableBeaconProxy.sol.func.html new file mode 100644 index 0000000000..72ecebac19 --- /dev/null +++ b/coverage/libraries/ClonableBeaconProxy.sol.func.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - libraries/ClonableBeaconProxy.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ClonableBeaconProxy.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
BeaconProxyFactory.calculateExpectedAddress0
BeaconProxyFactory.createProxy0
BeaconProxyFactory.getSalt0
BeaconProxyFactory.initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ClonableBeaconProxy.sol.gcov.html b/coverage/libraries/ClonableBeaconProxy.sol.gcov.html new file mode 100644 index 0000000000..1e581616e7 --- /dev/null +++ b/coverage/libraries/ClonableBeaconProxy.sol.gcov.html @@ -0,0 +1,141 @@ + + + + + + + LCOV - lcov.info - libraries/ClonableBeaconProxy.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ClonableBeaconProxy.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : // solhint-disable-next-line compiler-version
+       3                 :            : pragma solidity >=0.6.0 <0.9.0;
+       4                 :            : 
+       5                 :            : import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
+       6                 :            : import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
+       7                 :            : import "@openzeppelin/contracts/utils/Create2.sol";
+       8                 :            : 
+       9                 :            : interface ProxySetter {
+      10                 :            :     function beacon() external view returns (address);
+      11                 :            : }
+      12                 :            : 
+      13                 :            : contract ClonableBeaconProxy is BeaconProxy {
+      14                 :            :     constructor() BeaconProxy(ProxySetter(msg.sender).beacon(), "") {}
+      15                 :            : }
+      16                 :            : 
+      17                 :            : contract BeaconProxyFactory is ProxySetter {
+      18                 :            :     bytes32 public constant cloneableProxyHash = keccak256(type(ClonableBeaconProxy).creationCode);
+      19                 :            : 
+      20                 :            :     /**
+      21                 :            :      * @notice utility function used in ClonableBeaconProxy.
+      22                 :            :      * @dev this method makes it possible to use ClonableBeaconProxy.creationCode without encoding constructor parameters
+      23                 :            :      * @return the beacon to be used by the proxy contract.
+      24                 :            :      */
+      25                 :            :     address public override beacon;
+      26                 :            : 
+      27                 :            :     function initialize(address _beacon) external {
+      28         [ #  # ]:          0 :         require(_beacon != address(0), "INVALID_BEACON");
+      29         [ #  # ]:          0 :         require(beacon == address(0), "ALREADY_INIT");
+      30                 :          0 :         beacon = _beacon;
+      31                 :            :     }
+      32                 :            : 
+      33                 :            :     function getSalt(address user, bytes32 userSalt) public pure returns (bytes32) {
+      34                 :          0 :         return keccak256(abi.encode(user, userSalt));
+      35                 :            :     }
+      36                 :            : 
+      37                 :            :     function createProxy(bytes32 userSalt) external returns (address) {
+      38                 :            :         // deployment will fail and this function will revert if contract `salt` is not unique
+      39                 :          0 :         bytes32 salt = getSalt(msg.sender, userSalt);
+      40                 :          0 :         address createdContract = address(new ClonableBeaconProxy{ salt: salt }());
+      41                 :          0 :         return createdContract;
+      42                 :            :     }
+      43                 :            : 
+      44                 :            :     function calculateExpectedAddress(address user, bytes32 userSalt)
+      45                 :            :         public
+      46                 :            :         view
+      47                 :            :         returns (address)
+      48                 :            :     {
+      49                 :          0 :         bytes32 salt = getSalt(user, userSalt);
+      50                 :          0 :         return Create2.computeAddress(salt, cloneableProxyHash, address(this));
+      51                 :            :     }
+      52                 :            : 
+      53                 :            :     function calculateExpectedAddress(bytes32 salt) public view returns (address) {
+      54                 :          0 :         return Create2.computeAddress(salt, cloneableProxyHash, address(this));
+      55                 :            :     }
+      56                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/Cloneable.sol.func-sort-c.html b/coverage/libraries/Cloneable.sol.func-sort-c.html new file mode 100644 index 0000000000..68c91b8295 --- /dev/null +++ b/coverage/libraries/Cloneable.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - libraries/Cloneable.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - Cloneable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
Cloneable.isMaster0
Cloneable.safeSelfDestruct0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/Cloneable.sol.func.html b/coverage/libraries/Cloneable.sol.func.html new file mode 100644 index 0000000000..c7986cc2d1 --- /dev/null +++ b/coverage/libraries/Cloneable.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - libraries/Cloneable.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - Cloneable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
Cloneable.isMaster0
Cloneable.safeSelfDestruct0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/Cloneable.sol.gcov.html b/coverage/libraries/Cloneable.sol.gcov.html new file mode 100644 index 0000000000..e0cc61b704 --- /dev/null +++ b/coverage/libraries/Cloneable.sol.gcov.html @@ -0,0 +1,125 @@ + + + + + + + LCOV - lcov.info - libraries/Cloneable.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - Cloneable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:020.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2019-2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./ICloneable.sol";
+      22                 :            : 
+      23                 :            : contract Cloneable is ICloneable {
+      24                 :            :     string private constant NOT_CLONE = "NOT_CLONE";
+      25                 :            : 
+      26                 :            :     bool private isMasterCopy;
+      27                 :            : 
+      28                 :            :     constructor() {
+      29                 :            :         isMasterCopy = true;
+      30                 :            :     }
+      31                 :            : 
+      32                 :            :     function isMaster() external view override returns (bool) {
+      33                 :          0 :         return isMasterCopy;
+      34                 :            :     }
+      35                 :            : 
+      36                 :            :     function safeSelfDestruct(address payable dest) internal {
+      37         [ #  # ]:          0 :         require(!isMasterCopy, NOT_CLONE);
+      38                 :          0 :         selfdestruct(dest);
+      39                 :            :     }
+      40                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ERC165.sol.func-sort-c.html b/coverage/libraries/ERC165.sol.func-sort-c.html new file mode 100644 index 0000000000..789dc60044 --- /dev/null +++ b/coverage/libraries/ERC165.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - libraries/ERC165.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ERC165.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ERC165.supportsInterface768
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ERC165.sol.func.html b/coverage/libraries/ERC165.sol.func.html new file mode 100644 index 0000000000..85351d4658 --- /dev/null +++ b/coverage/libraries/ERC165.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - libraries/ERC165.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ERC165.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ERC165.supportsInterface768
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ERC165.sol.gcov.html b/coverage/libraries/ERC165.sol.gcov.html new file mode 100644 index 0000000000..d193de66ca --- /dev/null +++ b/coverage/libraries/ERC165.sol.gcov.html @@ -0,0 +1,117 @@ + + + + + + + LCOV - lcov.info - libraries/ERC165.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ERC165.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MIT
+       2                 :            : // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
+       3                 :            : 
+       4                 :            : // With pragma modification to support ^0.6.11
+       5                 :            : // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.6/contracts/utils/introspection/ERC165.sol
+       6                 :            : 
+       7                 :            : pragma solidity ^0.8.0;
+       8                 :            : 
+       9                 :            : import "./IERC165.sol";
+      10                 :            : 
+      11                 :            : /**
+      12                 :            :  * @dev Implementation of the {IERC165} interface.
+      13                 :            :  *
+      14                 :            :  * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
+      15                 :            :  * for the additional interface id that will be supported. For example:
+      16                 :            :  *
+      17                 :            :  * ```solidity
+      18                 :            :  * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
+      19                 :            :  *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
+      20                 :            :  * }
+      21                 :            :  * ```
+      22                 :            :  *
+      23                 :            :  * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
+      24                 :            :  */
+      25                 :            : abstract contract ERC165 is IERC165 {
+      26                 :            :     /**
+      27                 :            :      * @dev See {IERC165-supportsInterface}.
+      28                 :            :      */
+      29                 :            :     function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
+      30                 :        768 :         return interfaceId == type(IERC165).interfaceId;
+      31                 :            :     }
+      32                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ERC20Upgradeable.sol.func-sort-c.html b/coverage/libraries/ERC20Upgradeable.sol.func-sort-c.html new file mode 100644 index 0000000000..f38ddeb847 --- /dev/null +++ b/coverage/libraries/ERC20Upgradeable.sol.func-sort-c.html @@ -0,0 +1,165 @@ + + + + + + + LCOV - lcov.info - libraries/ERC20Upgradeable.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ERC20Upgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:386063.3 %
Date:2023-04-27 16:26:32Functions:132161.9 %
Branches:102245.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ERC20Upgradeable.__ERC20_init0
ERC20Upgradeable.__ERC20_init_unchained0
ERC20Upgradeable._burn0
ERC20Upgradeable._setupDecimals0
ERC20Upgradeable.allowance0
ERC20Upgradeable.decreaseAllowance0
ERC20Upgradeable.increaseAllowance0
ERC20Upgradeable.totalSupply0
ERC20Upgradeable._mint2
ERC20Upgradeable.transfer2
ERC20Upgradeable.approve4
ERC20Upgradeable._spendAllowance6
ERC20Upgradeable._transfer6
ERC20Upgradeable.transferFrom6
ERC20Upgradeable._afterTokenTransfer8
ERC20Upgradeable._approve8
ERC20Upgradeable._beforeTokenTransfer8
ERC20Upgradeable.decimals10
ERC20Upgradeable.name10
ERC20Upgradeable.symbol10
ERC20Upgradeable.balanceOf34
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ERC20Upgradeable.sol.func.html b/coverage/libraries/ERC20Upgradeable.sol.func.html new file mode 100644 index 0000000000..ee1e8d493e --- /dev/null +++ b/coverage/libraries/ERC20Upgradeable.sol.func.html @@ -0,0 +1,165 @@ + + + + + + + LCOV - lcov.info - libraries/ERC20Upgradeable.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ERC20Upgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:386063.3 %
Date:2023-04-27 16:26:32Functions:132161.9 %
Branches:102245.5 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ERC20Upgradeable.__ERC20_init0
ERC20Upgradeable.__ERC20_init_unchained0
ERC20Upgradeable._afterTokenTransfer8
ERC20Upgradeable._approve8
ERC20Upgradeable._beforeTokenTransfer8
ERC20Upgradeable._burn0
ERC20Upgradeable._mint2
ERC20Upgradeable._setupDecimals0
ERC20Upgradeable._spendAllowance6
ERC20Upgradeable._transfer6
ERC20Upgradeable.allowance0
ERC20Upgradeable.approve4
ERC20Upgradeable.balanceOf34
ERC20Upgradeable.decimals10
ERC20Upgradeable.decreaseAllowance0
ERC20Upgradeable.increaseAllowance0
ERC20Upgradeable.name10
ERC20Upgradeable.symbol10
ERC20Upgradeable.totalSupply0
ERC20Upgradeable.transfer2
ERC20Upgradeable.transferFrom6
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ERC20Upgradeable.sol.gcov.html b/coverage/libraries/ERC20Upgradeable.sol.gcov.html new file mode 100644 index 0000000000..4d64e14dee --- /dev/null +++ b/coverage/libraries/ERC20Upgradeable.sol.gcov.html @@ -0,0 +1,477 @@ + + + + + + + LCOV - lcov.info - libraries/ERC20Upgradeable.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ERC20Upgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:386063.3 %
Date:2023-04-27 16:26:32Functions:132161.9 %
Branches:102245.5 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MIT
+       2                 :            : // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)
+       3                 :            : 
+       4                 :            : pragma solidity ^0.8.0;
+       5                 :            : 
+       6                 :            : import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
+       7                 :            : import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
+       8                 :            : import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
+       9                 :            : import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
+      10                 :            : 
+      11                 :            : /**
+      12                 :            :  * @dev Implementation of the {IERC20} interface.
+      13                 :            :  *
+      14                 :            :  * This implementation is based on OpenZeppelin implementation (https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.8.3/contracts/token/ERC20/ERC20Upgradeable.sol)
+      15                 :            :  * with a small modification. OZ implementation removed `decimals` storage variable when they did upgrade to Solidity 0.8. Since we're already using older OZ implementation, here we're
+      16                 :            :  * adding back the `decimals` storage variable along with the appropriate getter and setter. That way we avoid changes in storage layout that would've happen due to OZ removing token
+      17                 :            :  * decimals storage variable.
+      18                 :            :  *
+      19                 :            :  */
+      20                 :            : contract ERC20Upgradeable is
+      21                 :            :     Initializable,
+      22                 :            :     ContextUpgradeable,
+      23                 :            :     IERC20Upgradeable,
+      24                 :            :     IERC20MetadataUpgradeable
+      25                 :            : {
+      26                 :            :     mapping(address => uint256) private _balances;
+      27                 :            : 
+      28                 :            :     mapping(address => mapping(address => uint256)) private _allowances;
+      29                 :            : 
+      30                 :            :     uint256 private _totalSupply;
+      31                 :            : 
+      32                 :            :     string private _name;
+      33                 :            :     string private _symbol;
+      34                 :            :     uint8 private _decimals;
+      35                 :            : 
+      36                 :            :     /**
+      37                 :            :      * @dev Sets the values for {name} and {symbol}.
+      38                 :            :      *
+      39                 :            :      * The default value of {decimals} is 18. To select a different value for
+      40                 :            :      * {decimals} you should overload it.
+      41                 :            :      *
+      42                 :            :      * All two of these values are immutable: they can only be set once during
+      43                 :            :      * construction.
+      44                 :            :      */
+      45                 :            :     function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
+      46                 :          0 :         __ERC20_init_unchained(name_, symbol_);
+      47                 :            :     }
+      48                 :            : 
+      49                 :            :     function __ERC20_init_unchained(
+      50                 :            :         string memory name_,
+      51                 :            :         string memory symbol_
+      52                 :            :     ) internal onlyInitializing {
+      53                 :          0 :         _name = name_;
+      54                 :          0 :         _symbol = symbol_;
+      55                 :          0 :         _decimals = 18;
+      56                 :            :     }
+      57                 :            : 
+      58                 :            :     /**
+      59                 :            :      * @dev Returns the name of the token.
+      60                 :            :      */
+      61                 :            :     function name() public view virtual override returns (string memory) {
+      62                 :         10 :         return _name;
+      63                 :            :     }
+      64                 :            : 
+      65                 :            :     /**
+      66                 :            :      * @dev Returns the symbol of the token, usually a shorter version of the
+      67                 :            :      * name.
+      68                 :            :      */
+      69                 :            :     function symbol() public view virtual override returns (string memory) {
+      70                 :         10 :         return _symbol;
+      71                 :            :     }
+      72                 :            : 
+      73                 :            :     /**
+      74                 :            :      * @dev Returns the number of decimals used to get its user representation.
+      75                 :            :      * For example, if `decimals` equals `2`, a balance of `505` tokens should
+      76                 :            :      * be displayed to a user as `5.05` (`505 / 10 ** 2`).
+      77                 :            :      *
+      78                 :            :      * Tokens usually opt for a value of 18, imitating the relationship between
+      79                 :            :      * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
+      80                 :            :      * called;
+      81                 :            :      *
+      82                 :            :      * NOTE: This information is only used for _display_ purposes: it in
+      83                 :            :      * no way affects any of the arithmetic of the contract, including
+      84                 :            :      * {IERC20-balanceOf} and {IERC20-transfer}.
+      85                 :            :      */
+      86                 :            :     function decimals() public view virtual override returns (uint8) {
+      87                 :         10 :         return _decimals;
+      88                 :            :     }
+      89                 :            : 
+      90                 :            :     /**
+      91                 :            :      * @dev See {IERC20-totalSupply}.
+      92                 :            :      */
+      93                 :            :     function totalSupply() public view virtual override returns (uint256) {
+      94                 :          0 :         return _totalSupply;
+      95                 :            :     }
+      96                 :            : 
+      97                 :            :     /**
+      98                 :            :      * @dev See {IERC20-balanceOf}.
+      99                 :            :      */
+     100                 :            :     function balanceOf(address account) public view virtual override returns (uint256) {
+     101                 :         34 :         return _balances[account];
+     102                 :            :     }
+     103                 :            : 
+     104                 :            :     /**
+     105                 :            :      * @dev See {IERC20-transfer}.
+     106                 :            :      *
+     107                 :            :      * Requirements:
+     108                 :            :      *
+     109                 :            :      * - `to` cannot be the zero address.
+     110                 :            :      * - the caller must have a balance of at least `amount`.
+     111                 :            :      */
+     112                 :            :     function transfer(address to, uint256 amount) public virtual override returns (bool) {
+     113                 :          2 :         address owner = _msgSender();
+     114                 :          2 :         _transfer(owner, to, amount);
+     115                 :          2 :         return true;
+     116                 :            :     }
+     117                 :            : 
+     118                 :            :     /**
+     119                 :            :      * @dev See {IERC20-allowance}.
+     120                 :            :      */
+     121                 :            :     function allowance(
+     122                 :            :         address owner,
+     123                 :            :         address spender
+     124                 :            :     ) public view virtual override returns (uint256) {
+     125                 :          6 :         return _allowances[owner][spender];
+     126                 :            :     }
+     127                 :            : 
+     128                 :            :     /**
+     129                 :            :      * @dev See {IERC20-approve}.
+     130                 :            :      *
+     131                 :            :      * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
+     132                 :            :      * `transferFrom`. This is semantically equivalent to an infinite approval.
+     133                 :            :      *
+     134                 :            :      * Requirements:
+     135                 :            :      *
+     136                 :            :      * - `spender` cannot be the zero address.
+     137                 :            :      */
+     138                 :            :     function approve(address spender, uint256 amount) public virtual override returns (bool) {
+     139                 :          4 :         address owner = _msgSender();
+     140                 :          4 :         _approve(owner, spender, amount);
+     141                 :          4 :         return true;
+     142                 :            :     }
+     143                 :            : 
+     144                 :            :     /**
+     145                 :            :      * @dev See {IERC20-transferFrom}.
+     146                 :            :      *
+     147                 :            :      * Emits an {Approval} event indicating the updated allowance. This is not
+     148                 :            :      * required by the EIP. See the note at the beginning of {ERC20}.
+     149                 :            :      *
+     150                 :            :      * NOTE: Does not update the allowance if the current allowance
+     151                 :            :      * is the maximum `uint256`.
+     152                 :            :      *
+     153                 :            :      * Requirements:
+     154                 :            :      *
+     155                 :            :      * - `from` and `to` cannot be the zero address.
+     156                 :            :      * - `from` must have a balance of at least `amount`.
+     157                 :            :      * - the caller must have allowance for ``from``'s tokens of at least
+     158                 :            :      * `amount`.
+     159                 :            :      */
+     160                 :            :     function transferFrom(
+     161                 :            :         address from,
+     162                 :            :         address to,
+     163                 :            :         uint256 amount
+     164                 :            :     ) public virtual override returns (bool) {
+     165                 :          6 :         address spender = _msgSender();
+     166                 :          6 :         _spendAllowance(from, spender, amount);
+     167                 :          4 :         _transfer(from, to, amount);
+     168                 :          4 :         return true;
+     169                 :            :     }
+     170                 :            : 
+     171                 :            :     /**
+     172                 :            :      * @dev Atomically increases the allowance granted to `spender` by the caller.
+     173                 :            :      *
+     174                 :            :      * This is an alternative to {approve} that can be used as a mitigation for
+     175                 :            :      * problems described in {IERC20-approve}.
+     176                 :            :      *
+     177                 :            :      * Emits an {Approval} event indicating the updated allowance.
+     178                 :            :      *
+     179                 :            :      * Requirements:
+     180                 :            :      *
+     181                 :            :      * - `spender` cannot be the zero address.
+     182                 :            :      */
+     183                 :            :     function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
+     184                 :          0 :         address owner = _msgSender();
+     185                 :          0 :         _approve(owner, spender, allowance(owner, spender) + addedValue);
+     186                 :          0 :         return true;
+     187                 :            :     }
+     188                 :            : 
+     189                 :            :     /**
+     190                 :            :      * @dev Atomically decreases the allowance granted to `spender` by the caller.
+     191                 :            :      *
+     192                 :            :      * This is an alternative to {approve} that can be used as a mitigation for
+     193                 :            :      * problems described in {IERC20-approve}.
+     194                 :            :      *
+     195                 :            :      * Emits an {Approval} event indicating the updated allowance.
+     196                 :            :      *
+     197                 :            :      * Requirements:
+     198                 :            :      *
+     199                 :            :      * - `spender` cannot be the zero address.
+     200                 :            :      * - `spender` must have allowance for the caller of at least
+     201                 :            :      * `subtractedValue`.
+     202                 :            :      */
+     203                 :            :     function decreaseAllowance(
+     204                 :            :         address spender,
+     205                 :            :         uint256 subtractedValue
+     206                 :            :     ) public virtual returns (bool) {
+     207                 :          0 :         address owner = _msgSender();
+     208                 :          0 :         uint256 currentAllowance = allowance(owner, spender);
+     209         [ #  # ]:          0 :         require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
+     210                 :            :         unchecked {
+     211                 :          0 :             _approve(owner, spender, currentAllowance - subtractedValue);
+     212                 :            :         }
+     213                 :            : 
+     214                 :          0 :         return true;
+     215                 :            :     }
+     216                 :            : 
+     217                 :            :     /**
+     218                 :            :      * @dev Moves `amount` of tokens from `from` to `to`.
+     219                 :            :      *
+     220                 :            :      * This internal function is equivalent to {transfer}, and can be used to
+     221                 :            :      * e.g. implement automatic token fees, slashing mechanisms, etc.
+     222                 :            :      *
+     223                 :            :      * Emits a {Transfer} event.
+     224                 :            :      *
+     225                 :            :      * Requirements:
+     226                 :            :      *
+     227                 :            :      * - `from` cannot be the zero address.
+     228                 :            :      * - `to` cannot be the zero address.
+     229                 :            :      * - `from` must have a balance of at least `amount`.
+     230                 :            :      */
+     231                 :            :     function _transfer(address from, address to, uint256 amount) internal virtual {
+     232         [ #  + ]:          6 :         require(from != address(0), "ERC20: transfer from the zero address");
+     233         [ #  + ]:          6 :         require(to != address(0), "ERC20: transfer to the zero address");
+     234                 :            : 
+     235                 :          6 :         _beforeTokenTransfer(from, to, amount);
+     236                 :            : 
+     237                 :          6 :         uint256 fromBalance = _balances[from];
+     238         [ #  + ]:          6 :         require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
+     239                 :            :         unchecked {
+     240                 :          6 :             _balances[from] = fromBalance - amount;
+     241                 :            :             // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
+     242                 :            :             // decrementing then incrementing.
+     243                 :          6 :             _balances[to] += amount;
+     244                 :            :         }
+     245                 :            : 
+     246                 :          6 :         emit Transfer(from, to, amount);
+     247                 :            : 
+     248                 :          6 :         _afterTokenTransfer(from, to, amount);
+     249                 :            :     }
+     250                 :            : 
+     251                 :            :     /** @dev Creates `amount` tokens and assigns them to `account`, increasing
+     252                 :            :      * the total supply.
+     253                 :            :      *
+     254                 :            :      * Emits a {Transfer} event with `from` set to the zero address.
+     255                 :            :      *
+     256                 :            :      * Requirements:
+     257                 :            :      *
+     258                 :            :      * - `account` cannot be the zero address.
+     259                 :            :      */
+     260                 :            :     function _mint(address account, uint256 amount) internal virtual {
+     261         [ #  + ]:          2 :         require(account != address(0), "ERC20: mint to the zero address");
+     262                 :            : 
+     263                 :          2 :         _beforeTokenTransfer(address(0), account, amount);
+     264                 :            : 
+     265                 :          2 :         _totalSupply += amount;
+     266                 :            :         unchecked {
+     267                 :            :             // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
+     268                 :          2 :             _balances[account] += amount;
+     269                 :            :         }
+     270                 :          2 :         emit Transfer(address(0), account, amount);
+     271                 :            : 
+     272                 :          2 :         _afterTokenTransfer(address(0), account, amount);
+     273                 :            :     }
+     274                 :            : 
+     275                 :            :     /**
+     276                 :            :      * @dev Destroys `amount` tokens from `account`, reducing the
+     277                 :            :      * total supply.
+     278                 :            :      *
+     279                 :            :      * Emits a {Transfer} event with `to` set to the zero address.
+     280                 :            :      *
+     281                 :            :      * Requirements:
+     282                 :            :      *
+     283                 :            :      * - `account` cannot be the zero address.
+     284                 :            :      * - `account` must have at least `amount` tokens.
+     285                 :            :      */
+     286                 :            :     function _burn(address account, uint256 amount) internal virtual {
+     287         [ #  # ]:          0 :         require(account != address(0), "ERC20: burn from the zero address");
+     288                 :            : 
+     289                 :          0 :         _beforeTokenTransfer(account, address(0), amount);
+     290                 :            : 
+     291                 :          0 :         uint256 accountBalance = _balances[account];
+     292         [ #  # ]:          0 :         require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
+     293                 :            :         unchecked {
+     294                 :          0 :             _balances[account] = accountBalance - amount;
+     295                 :            :             // Overflow not possible: amount <= accountBalance <= totalSupply.
+     296                 :          0 :             _totalSupply -= amount;
+     297                 :            :         }
+     298                 :            : 
+     299                 :          0 :         emit Transfer(account, address(0), amount);
+     300                 :            : 
+     301                 :          0 :         _afterTokenTransfer(account, address(0), amount);
+     302                 :            :     }
+     303                 :            : 
+     304                 :            :     /**
+     305                 :            :      * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
+     306                 :            :      *
+     307                 :            :      * This internal function is equivalent to `approve`, and can be used to
+     308                 :            :      * e.g. set automatic allowances for certain subsystems, etc.
+     309                 :            :      *
+     310                 :            :      * Emits an {Approval} event.
+     311                 :            :      *
+     312                 :            :      * Requirements:
+     313                 :            :      *
+     314                 :            :      * - `owner` cannot be the zero address.
+     315                 :            :      * - `spender` cannot be the zero address.
+     316                 :            :      */
+     317                 :            :     function _approve(address owner, address spender, uint256 amount) internal virtual {
+     318         [ #  + ]:          8 :         require(owner != address(0), "ERC20: approve from the zero address");
+     319         [ #  + ]:          8 :         require(spender != address(0), "ERC20: approve to the zero address");
+     320                 :            : 
+     321                 :          8 :         _allowances[owner][spender] = amount;
+     322                 :          8 :         emit Approval(owner, spender, amount);
+     323                 :            :     }
+     324                 :            : 
+     325                 :            :     /**
+     326                 :            :      * @dev Sets {decimals} to a value other than the default one of 18.
+     327                 :            :      *
+     328                 :            :      * WARNING: This function should only be called from the constructor. Most
+     329                 :            :      * applications that interact with token contracts will not expect
+     330                 :            :      * {decimals} to ever change, and may work incorrectly if it does.
+     331                 :            :      */
+     332                 :            :     function _setupDecimals(uint8 decimals_) internal virtual {
+     333                 :          0 :         _decimals = decimals_;
+     334                 :            :     }
+     335                 :            : 
+     336                 :            :     /**
+     337                 :            :      * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
+     338                 :            :      *
+     339                 :            :      * Does not update the allowance amount in case of infinite allowance.
+     340                 :            :      * Revert if not enough allowance is available.
+     341                 :            :      *
+     342                 :            :      * Might emit an {Approval} event.
+     343                 :            :      */
+     344                 :            :     function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
+     345                 :          6 :         uint256 currentAllowance = allowance(owner, spender);
+     346         [ +  + ]:          6 :         if (currentAllowance != type(uint256).max) {
+     347         [ +  + ]:          6 :             require(currentAllowance >= amount, "ERC20: insufficient allowance");
+     348                 :            :             unchecked {
+     349                 :          4 :                 _approve(owner, spender, currentAllowance - amount);
+     350                 :            :             }
+     351                 :            :         }
+     352                 :            :     }
+     353                 :            : 
+     354                 :            :     /**
+     355                 :            :      * @dev Hook that is called before any transfer of tokens. This includes
+     356                 :            :      * minting and burning.
+     357                 :            :      *
+     358                 :            :      * Calling conditions:
+     359                 :            :      *
+     360                 :            :      * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
+     361                 :            :      * will be transferred to `to`.
+     362                 :            :      * - when `from` is zero, `amount` tokens will be minted for `to`.
+     363                 :            :      * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
+     364                 :            :      * - `from` and `to` are never both zero.
+     365                 :            :      *
+     366                 :            :      * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
+     367                 :            :      */
+     368                 :            :     function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
+     369                 :            : 
+     370                 :            :     /**
+     371                 :            :      * @dev Hook that is called after any transfer of tokens. This includes
+     372                 :            :      * minting and burning.
+     373                 :            :      *
+     374                 :            :      * Calling conditions:
+     375                 :            :      *
+     376                 :            :      * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
+     377                 :            :      * has been transferred to `to`.
+     378                 :            :      * - when `from` is zero, `amount` tokens have been minted for `to`.
+     379                 :            :      * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
+     380                 :            :      * - `from` and `to` are never both zero.
+     381                 :            :      *
+     382                 :            :      * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
+     383                 :            :      */
+     384                 :            :     function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
+     385                 :            : 
+     386                 :            :     /**
+     387                 :            :      * @dev This empty reserved space is put in place to allow future versions to add new
+     388                 :            :      * variables without shifting down storage in the inheritance chain.
+     389                 :            :      * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
+     390                 :            :      */
+     391                 :            :     uint256[44] private __gap;
+     392                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/L2CustomGatewayToken.sol.func-sort-c.html b/coverage/libraries/L2CustomGatewayToken.sol.func-sort-c.html new file mode 100644 index 0000000000..b4eed9ebdc --- /dev/null +++ b/coverage/libraries/L2CustomGatewayToken.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - libraries/L2CustomGatewayToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - L2CustomGatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2CustomGatewayToken.initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/L2CustomGatewayToken.sol.func.html b/coverage/libraries/L2CustomGatewayToken.sol.func.html new file mode 100644 index 0000000000..ef4c2db67a --- /dev/null +++ b/coverage/libraries/L2CustomGatewayToken.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - libraries/L2CustomGatewayToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - L2CustomGatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2CustomGatewayToken.initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/L2CustomGatewayToken.sol.gcov.html b/coverage/libraries/L2CustomGatewayToken.sol.gcov.html new file mode 100644 index 0000000000..fb5554bb3e --- /dev/null +++ b/coverage/libraries/L2CustomGatewayToken.sol.gcov.html @@ -0,0 +1,130 @@ + + + + + + + LCOV - lcov.info - libraries/L2CustomGatewayToken.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - L2CustomGatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./L2GatewayToken.sol";
+      22                 :            : 
+      23                 :            : /**
+      24                 :            :  * @title A basic custom token contract that can be used with the custom gateway
+      25                 :            :  */
+      26                 :            : contract L2CustomGatewayToken is L2GatewayToken {
+      27                 :            :     /**
+      28                 :            :      * @notice initialize the token
+      29                 :            :      * @dev the L2 bridge assumes this does not fail or revert
+      30                 :            :      * @param name_ ERC20 token name
+      31                 :            :      * @param symbol_ ERC20 token symbol
+      32                 :            :      * @param decimals_ ERC20 decimals
+      33                 :            :      * @param l2Gateway_ L2 gateway this token communicates with
+      34                 :            :      * @param l1Counterpart_ L1 address of ERC20
+      35                 :            :      */
+      36                 :            :     function initialize(
+      37                 :            :         string memory name_,
+      38                 :            :         string memory symbol_,
+      39                 :            :         uint8 decimals_,
+      40                 :            :         address l2Gateway_,
+      41                 :            :         address l1Counterpart_
+      42                 :            :     ) public virtual initializer {
+      43                 :          0 :         _initialize(name_, symbol_, decimals_, l2Gateway_, l1Counterpart_);
+      44                 :            :     }
+      45                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/L2GatewayToken.sol.func-sort-c.html b/coverage/libraries/L2GatewayToken.sol.func-sort-c.html new file mode 100644 index 0000000000..320d3020db --- /dev/null +++ b/coverage/libraries/L2GatewayToken.sol.func-sort-c.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - libraries/L2GatewayToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - L2GatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2GatewayToken._initialize0
L2GatewayToken.bridgeBurn0
L2GatewayToken.bridgeMint0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/L2GatewayToken.sol.func.html b/coverage/libraries/L2GatewayToken.sol.func.html new file mode 100644 index 0000000000..4332ed4944 --- /dev/null +++ b/coverage/libraries/L2GatewayToken.sol.func.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - libraries/L2GatewayToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - L2GatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2GatewayToken._initialize0
L2GatewayToken.bridgeBurn0
L2GatewayToken.bridgeMint0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/L2GatewayToken.sol.gcov.html b/coverage/libraries/L2GatewayToken.sol.gcov.html new file mode 100644 index 0000000000..fc000103bd --- /dev/null +++ b/coverage/libraries/L2GatewayToken.sol.gcov.html @@ -0,0 +1,164 @@ + + + + + + + LCOV - lcov.info - libraries/L2GatewayToken.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - L2GatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:040.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./aeERC20.sol";
+      22                 :            : import "./BytesParser.sol";
+      23                 :            : import "../arbitrum/IArbToken.sol";
+      24                 :            : 
+      25                 :            : /**
+      26                 :            :  * @title Standard (i.e., non-custom) contract used as a base for different L2 Gateways
+      27                 :            :  */
+      28                 :            : abstract contract L2GatewayToken is aeERC20, IArbToken {
+      29                 :            :     address public l2Gateway;
+      30                 :            :     address public override l1Address;
+      31                 :            : 
+      32                 :            :     modifier onlyGateway() {
+      33                 :            :         require(msg.sender == l2Gateway, "ONLY_GATEWAY");
+      34                 :            :         _;
+      35                 :            :     }
+      36                 :            : 
+      37                 :            :     /**
+      38                 :            :      * @notice initialize the token
+      39                 :            :      * @dev the L2 bridge assumes this does not fail or revert
+      40                 :            :      * @param name_ ERC20 token name
+      41                 :            :      * @param symbol_ ERC20 token symbol
+      42                 :            :      * @param decimals_ ERC20 decimals
+      43                 :            :      * @param l2Gateway_ L2 gateway this token communicates with
+      44                 :            :      * @param l1Counterpart_ L1 address of ERC20
+      45                 :            :      */
+      46                 :            :     function _initialize(
+      47                 :            :         string memory name_,
+      48                 :            :         string memory symbol_,
+      49                 :            :         uint8 decimals_,
+      50                 :            :         address l2Gateway_,
+      51                 :            :         address l1Counterpart_
+      52                 :            :     ) internal virtual {
+      53         [ #  # ]:          0 :         require(l2Gateway_ != address(0), "INVALID_GATEWAY");
+      54         [ #  # ]:          0 :         require(l2Gateway == address(0), "ALREADY_INIT");
+      55                 :          0 :         l2Gateway = l2Gateway_;
+      56                 :          0 :         l1Address = l1Counterpart_;
+      57                 :            : 
+      58                 :          0 :         aeERC20._initialize(name_, symbol_, decimals_);
+      59                 :            :     }
+      60                 :            : 
+      61                 :            :     /**
+      62                 :            :      * @notice Mint tokens on L2. Callable path is L1Gateway depositToken (which handles L1 escrow), which triggers L2Gateway, which calls this
+      63                 :            :      * @param account recipient of tokens
+      64                 :            :      * @param amount amount of tokens minted
+      65                 :            :      */
+      66                 :            :     function bridgeMint(address account, uint256 amount) external virtual override onlyGateway {
+      67                 :          0 :         _mint(account, amount);
+      68                 :            :     }
+      69                 :            : 
+      70                 :            :     /**
+      71                 :            :      * @notice Burn tokens on L2.
+      72                 :            :      * @dev only the token bridge can call this
+      73                 :            :      * @param account owner of tokens
+      74                 :            :      * @param amount amount of tokens burnt
+      75                 :            :      */
+      76                 :            :     function bridgeBurn(address account, uint256 amount) external virtual override onlyGateway {
+      77                 :          0 :         _burn(account, amount);
+      78                 :            :     }
+      79                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ProxyUtil.sol.func-sort-c.html b/coverage/libraries/ProxyUtil.sol.func-sort-c.html new file mode 100644 index 0000000000..cbf0b9e395 --- /dev/null +++ b/coverage/libraries/ProxyUtil.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - libraries/ProxyUtil.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ProxyUtil.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ProxyUtil.getProxyAdmin0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ProxyUtil.sol.func.html b/coverage/libraries/ProxyUtil.sol.func.html new file mode 100644 index 0000000000..cb2720bb8e --- /dev/null +++ b/coverage/libraries/ProxyUtil.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - libraries/ProxyUtil.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ProxyUtil.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ProxyUtil.getProxyAdmin0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/ProxyUtil.sol.gcov.html b/coverage/libraries/ProxyUtil.sol.gcov.html new file mode 100644 index 0000000000..6276f6746f --- /dev/null +++ b/coverage/libraries/ProxyUtil.sol.gcov.html @@ -0,0 +1,116 @@ + + + + + + + LCOV - lcov.info - libraries/ProxyUtil.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - ProxyUtil.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : library ProxyUtil {
+      22                 :            :     function getProxyAdmin() internal view returns (address admin) {
+      23                 :            :         // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/proxy/TransparentUpgradeableProxy.sol#L48
+      24                 :            :         // Storage slot with the admin of the proxy contract.
+      25                 :            :         // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
+      26                 :          0 :         bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
+      27                 :            :         assembly {
+      28                 :          0 :             admin := sload(slot)
+      29                 :            :         }
+      30                 :            :     }
+      31                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/TransferAndCallToken.sol.func-sort-c.html b/coverage/libraries/TransferAndCallToken.sol.func-sort-c.html new file mode 100644 index 0000000000..5be6e1f45d --- /dev/null +++ b/coverage/libraries/TransferAndCallToken.sol.func-sort-c.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - libraries/TransferAndCallToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - TransferAndCallToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TransferAndCallToken.contractFallback0
TransferAndCallToken.isContract0
TransferAndCallToken.transferAndCall0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/TransferAndCallToken.sol.func.html b/coverage/libraries/TransferAndCallToken.sol.func.html new file mode 100644 index 0000000000..c7246bb1a2 --- /dev/null +++ b/coverage/libraries/TransferAndCallToken.sol.func.html @@ -0,0 +1,93 @@ + + + + + + + LCOV - lcov.info - libraries/TransferAndCallToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - TransferAndCallToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TransferAndCallToken.contractFallback0
TransferAndCallToken.isContract0
TransferAndCallToken.transferAndCall0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/TransferAndCallToken.sol.gcov.html b/coverage/libraries/TransferAndCallToken.sol.gcov.html new file mode 100644 index 0000000000..2c301300f5 --- /dev/null +++ b/coverage/libraries/TransferAndCallToken.sol.gcov.html @@ -0,0 +1,136 @@ + + + + + + + LCOV - lcov.info - libraries/TransferAndCallToken.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - TransferAndCallToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:020.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MIT
+       2                 :            : // solhint-disable-next-line compiler-version
+       3                 :            : pragma solidity >0.6.0 <0.9.0;
+       4                 :            : 
+       5                 :            : import "./ERC20Upgradeable.sol";
+       6                 :            : import "./ITransferAndCall.sol";
+       7                 :            : 
+       8                 :            : // Implementation from https://github.com/smartcontractkit/LinkToken/blob/master/contracts/v0.6/TransferAndCallToken.sol
+       9                 :            : /**
+      10                 :            :  * @notice based on Implementation from https://github.com/smartcontractkit/LinkToken/blob/master/contracts/v0.6/ERC677Token.sol
+      11                 :            :  * The implementation doesn't return a bool on onTokenTransfer. This is similar to the proposed 677 standard, but still incompatible - thus we don't refer to it as such.
+      12                 :            :  */
+      13                 :            : abstract contract TransferAndCallToken is ERC20Upgradeable, ITransferAndCall {
+      14                 :            :     /**
+      15                 :            :      * @dev transfer token to a contract address with additional data if the recipient is a contact.
+      16                 :            :      * @param _to The address to transfer to.
+      17                 :            :      * @param _value The amount to be transferred.
+      18                 :            :      * @param _data The extra data to be passed to the receiving contract.
+      19                 :            :      */
+      20                 :            :     function transferAndCall(
+      21                 :            :         address _to,
+      22                 :            :         uint256 _value,
+      23                 :            :         bytes memory _data
+      24                 :            :     ) public virtual override returns (bool success) {
+      25                 :          0 :         super.transfer(_to, _value);
+      26                 :          0 :         emit Transfer(msg.sender, _to, _value, _data);
+      27         [ #  # ]:          0 :         if (isContract(_to)) {
+      28                 :          0 :             contractFallback(_to, _value, _data);
+      29                 :            :         }
+      30                 :          0 :         return true;
+      31                 :            :     }
+      32                 :            : 
+      33                 :            :     // PRIVATE
+      34                 :            : 
+      35                 :            :     function contractFallback(
+      36                 :            :         address _to,
+      37                 :            :         uint256 _value,
+      38                 :            :         bytes memory _data
+      39                 :            :     ) private {
+      40                 :          0 :         ITransferAndCallReceiver receiver = ITransferAndCallReceiver(_to);
+      41                 :          0 :         receiver.onTokenTransfer(msg.sender, _value, _data);
+      42                 :            :     }
+      43                 :            : 
+      44                 :            :     function isContract(address _addr) private view returns (bool hasCode) {
+      45                 :          0 :         uint256 length;
+      46                 :            :         assembly {
+      47                 :          0 :             length := extcodesize(_addr)
+      48                 :            :         }
+      49                 :          0 :         return length > 0;
+      50                 :            :     }
+      51                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/Whitelist.sol.func-sort-c.html b/coverage/libraries/Whitelist.sol.func-sort-c.html new file mode 100644 index 0000000000..3141a218fa --- /dev/null +++ b/coverage/libraries/Whitelist.sol.func-sort-c.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - libraries/Whitelist.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - Whitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
Whitelist.setOwner0
Whitelist.setWhitelist0
Whitelist.triggerConsumers0
WhitelistConsumer.updateWhitelistSource0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/Whitelist.sol.func.html b/coverage/libraries/Whitelist.sol.func.html new file mode 100644 index 0000000000..065adddc61 --- /dev/null +++ b/coverage/libraries/Whitelist.sol.func.html @@ -0,0 +1,97 @@ + + + + + + + LCOV - lcov.info - libraries/Whitelist.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - Whitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
Whitelist.setOwner0
Whitelist.setWhitelist0
Whitelist.triggerConsumers0
WhitelistConsumer.updateWhitelistSource0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/Whitelist.sol.gcov.html b/coverage/libraries/Whitelist.sol.gcov.html new file mode 100644 index 0000000000..99a9ebc96c --- /dev/null +++ b/coverage/libraries/Whitelist.sol.gcov.html @@ -0,0 +1,161 @@ + + + + + + + LCOV - lcov.info - libraries/Whitelist.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - Whitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : abstract contract WhitelistConsumer {
+      22                 :            :     address public whitelist;
+      23                 :            : 
+      24                 :            :     event WhitelistSourceUpdated(address newSource);
+      25                 :            : 
+      26                 :            :     modifier onlyWhitelisted() {
+      27                 :            :         if (whitelist != address(0)) {
+      28                 :            :             require(Whitelist(whitelist).isAllowed(msg.sender), "NOT_WHITELISTED");
+      29                 :            :         }
+      30                 :            :         _;
+      31                 :            :     }
+      32                 :            : 
+      33                 :            :     function updateWhitelistSource(address newSource) external {
+      34         [ #  # ]:          0 :         require(msg.sender == whitelist, "NOT_FROM_LIST");
+      35                 :          0 :         whitelist = newSource;
+      36                 :          0 :         emit WhitelistSourceUpdated(newSource);
+      37                 :            :     }
+      38                 :            : }
+      39                 :            : 
+      40                 :            : contract Whitelist {
+      41                 :            :     address public owner;
+      42                 :            :     mapping(address => bool) public isAllowed;
+      43                 :            : 
+      44                 :            :     event OwnerUpdated(address newOwner);
+      45                 :            :     event WhitelistUpgraded(address newWhitelist, address[] targets);
+      46                 :            : 
+      47                 :            :     constructor() {
+      48                 :            :         owner = msg.sender;
+      49                 :            :     }
+      50                 :            : 
+      51                 :            :     modifier onlyOwner() {
+      52                 :            :         require(msg.sender == owner, "ONLY_OWNER");
+      53                 :            :         _;
+      54                 :            :     }
+      55                 :            : 
+      56                 :            :     function setOwner(address newOwner) external onlyOwner {
+      57                 :          0 :         owner = newOwner;
+      58                 :          0 :         emit OwnerUpdated(newOwner);
+      59                 :            :     }
+      60                 :            : 
+      61                 :            :     function setWhitelist(address[] memory user, bool[] memory val) external onlyOwner {
+      62         [ #  # ]:          0 :         require(user.length == val.length, "INVALID_INPUT");
+      63                 :            : 
+      64                 :          0 :         for (uint256 i = 0; i < user.length; i++) {
+      65                 :          0 :             isAllowed[user[i]] = val[i];
+      66                 :            :         }
+      67                 :            :     }
+      68                 :            : 
+      69                 :            :     // set new whitelist to address(0) to disable whitelist
+      70                 :            :     function triggerConsumers(address newWhitelist, address[] memory targets) external onlyOwner {
+      71                 :          0 :         for (uint256 i = 0; i < targets.length; i++) {
+      72                 :          0 :             WhitelistConsumer(targets[i]).updateWhitelistSource(newWhitelist);
+      73                 :            :         }
+      74                 :          0 :         emit WhitelistUpgraded(newWhitelist, targets);
+      75                 :            :     }
+      76                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/aeERC20.sol.func-sort-c.html b/coverage/libraries/aeERC20.sol.func-sort-c.html new file mode 100644 index 0000000000..df6763dec5 --- /dev/null +++ b/coverage/libraries/aeERC20.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - libraries/aeERC20.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - aeERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
aeERC20._initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/aeERC20.sol.func.html b/coverage/libraries/aeERC20.sol.func.html new file mode 100644 index 0000000000..43a24228c2 --- /dev/null +++ b/coverage/libraries/aeERC20.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - libraries/aeERC20.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - aeERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
aeERC20._initialize0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/aeERC20.sol.gcov.html b/coverage/libraries/aeERC20.sol.gcov.html new file mode 100644 index 0000000000..840ac6b19f --- /dev/null +++ b/coverage/libraries/aeERC20.sol.gcov.html @@ -0,0 +1,129 @@ + + + + + + + LCOV - lcov.info - libraries/aeERC20.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - aeERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../libraries/draft-ERC20PermitUpgradeable.sol";
+      22                 :            : import "./TransferAndCallToken.sol";
+      23                 :            : 
+      24                 :            : /// @title Arbitrum extended ERC20
+      25                 :            : /// @notice The recommended ERC20 implementation for Layer 2 tokens
+      26                 :            : /// @dev This implements the ERC20 standard with transferAndCall extenstion/affordances
+      27                 :            : contract aeERC20 is ERC20PermitUpgradeable, TransferAndCallToken {
+      28                 :            :     using AddressUpgradeable for address;
+      29                 :            : 
+      30                 :            :     constructor() initializer {
+      31                 :            :         // this is expected to be used as the logic contract behind a proxy
+      32                 :            :         // override the constructor if you don't wish to use the initialize method
+      33                 :            :     }
+      34                 :            : 
+      35                 :            :     function _initialize(
+      36                 :            :         string memory name_,
+      37                 :            :         string memory symbol_,
+      38                 :            :         uint8 decimals_
+      39                 :            :     ) internal initializer {
+      40                 :          0 :         __ERC20Permit_init(name_);
+      41                 :          0 :         __ERC20_init(name_, symbol_);
+      42                 :          0 :         _setupDecimals(decimals_);
+      43                 :            :     }
+      44                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/aeWETH.sol.func-sort-c.html b/coverage/libraries/aeWETH.sol.func-sort-c.html new file mode 100644 index 0000000000..db4b6adcb0 --- /dev/null +++ b/coverage/libraries/aeWETH.sol.func-sort-c.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - libraries/aeWETH.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - aeWETH.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
aeWETH.bridgeBurn0
aeWETH.bridgeMint0
aeWETH.deposit0
aeWETH.depositTo0
aeWETH.initialize0
aeWETH.withdraw0
aeWETH.withdrawTo0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/aeWETH.sol.func.html b/coverage/libraries/aeWETH.sol.func.html new file mode 100644 index 0000000000..f4346e3b47 --- /dev/null +++ b/coverage/libraries/aeWETH.sol.func.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - libraries/aeWETH.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - aeWETH.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
aeWETH.bridgeBurn0
aeWETH.bridgeMint0
aeWETH.deposit0
aeWETH.depositTo0
aeWETH.initialize0
aeWETH.withdraw0
aeWETH.withdrawTo0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/aeWETH.sol.gcov.html b/coverage/libraries/aeWETH.sol.gcov.html new file mode 100644 index 0000000000..80ee708be1 --- /dev/null +++ b/coverage/libraries/aeWETH.sol.gcov.html @@ -0,0 +1,156 @@ + + + + + + + LCOV - lcov.info - libraries/aeWETH.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - aeWETH.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:040.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./L2GatewayToken.sol";
+      22                 :            : import "./IWETH9.sol";
+      23                 :            : 
+      24                 :            : /// @title Arbitrum extended WETH
+      25                 :            : contract aeWETH is L2GatewayToken, IWETH9 {
+      26                 :            :     function initialize(
+      27                 :            :         string memory name_,
+      28                 :            :         string memory symbol_,
+      29                 :            :         uint8 decimals_,
+      30                 :            :         address l2Gateway_,
+      31                 :            :         address l1Address_
+      32                 :            :     ) external {
+      33                 :          0 :         L2GatewayToken._initialize(name_, symbol_, decimals_, l2Gateway_, l1Address_);
+      34                 :            :     }
+      35                 :            : 
+      36                 :            :     function bridgeMint(
+      37                 :            :         address, /* account */
+      38                 :            :         uint256 /* amount */
+      39                 :            :     ) external virtual override {
+      40                 :            :         // we want weth to always be fully collaterized
+      41                 :          0 :         revert("NO_BRIDGE_MINT");
+      42                 :            :     }
+      43                 :            : 
+      44                 :            :     function bridgeBurn(address account, uint256 amount) external virtual override onlyGateway {
+      45                 :          0 :         _burn(account, amount);
+      46                 :          0 :         (bool success, ) = msg.sender.call{ value: amount }("");
+      47         [ #  # ]:          0 :         require(success, "FAIL_TRANSFER");
+      48                 :            :     }
+      49                 :            : 
+      50                 :            :     function deposit() external payable override {
+      51                 :          0 :         depositTo(msg.sender);
+      52                 :            :     }
+      53                 :            : 
+      54                 :            :     function withdraw(uint256 amount) external override {
+      55                 :          0 :         withdrawTo(msg.sender, amount);
+      56                 :            :     }
+      57                 :            : 
+      58                 :            :     function depositTo(address account) public payable {
+      59                 :          0 :         _mint(account, msg.value);
+      60                 :            :     }
+      61                 :            : 
+      62                 :            :     function withdrawTo(address account, uint256 amount) public {
+      63                 :          0 :         _burn(msg.sender, amount);
+      64                 :          0 :         (bool success, ) = account.call{ value: amount }("");
+      65         [ #  # ]:          0 :         require(success, "FAIL_TRANSFER");
+      66                 :            :     }
+      67                 :            : 
+      68                 :            :     receive() external payable {
+      69                 :            :         depositTo(msg.sender);
+      70                 :            :     }
+      71                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func-sort-c.html b/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func-sort-c.html new file mode 100644 index 0000000000..2b6431a5a8 --- /dev/null +++ b/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func-sort-c.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - libraries/draft-ERC20PermitUpgradeable.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - draft-ERC20PermitUpgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ERC20PermitUpgradeable.DOMAIN_SEPARATOR0
ERC20PermitUpgradeable.__ERC20Permit_init0
ERC20PermitUpgradeable.__ERC20Permit_init_unchained0
ERC20PermitUpgradeable._useNonce0
ERC20PermitUpgradeable.nonces0
ERC20PermitUpgradeable.permit0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func.html b/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func.html new file mode 100644 index 0000000000..72c3cf268a --- /dev/null +++ b/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - libraries/draft-ERC20PermitUpgradeable.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - draft-ERC20PermitUpgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:040.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ERC20PermitUpgradeable.DOMAIN_SEPARATOR0
ERC20PermitUpgradeable.__ERC20Permit_init0
ERC20PermitUpgradeable.__ERC20Permit_init_unchained0
ERC20PermitUpgradeable._useNonce0
ERC20PermitUpgradeable.nonces0
ERC20PermitUpgradeable.permit0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/draft-ERC20PermitUpgradeable.sol.gcov.html b/coverage/libraries/draft-ERC20PermitUpgradeable.sol.gcov.html new file mode 100644 index 0000000000..848e81f72a --- /dev/null +++ b/coverage/libraries/draft-ERC20PermitUpgradeable.sol.gcov.html @@ -0,0 +1,199 @@ + + + + + + + LCOV - lcov.info - libraries/draft-ERC20PermitUpgradeable.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries - draft-ERC20PermitUpgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:040.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: MIT
+       2                 :            : // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol)
+       3                 :            : 
+       4                 :            : pragma solidity ^0.8.0;
+       5                 :            : 
+       6                 :            : import "./ERC20Upgradeable.sol";
+       7                 :            : import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
+       8                 :            : import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol";
+       9                 :            : import "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
+      10                 :            : import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
+      11                 :            : import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
+      12                 :            : 
+      13                 :            : /**
+      14                 :            :  * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
+      15                 :            :  * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
+      16                 :            :  *
+      17                 :            :  * This implementation is based on OpenZeppelin implementation (https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol).
+      18                 :            :  * The only difference is that we are importing our own `ERC20Upgradeable` implementation instead of the OpenZeppelin's one.
+      19                 :            :  *
+      20                 :            :  */
+      21                 :            : abstract contract ERC20PermitUpgradeable is
+      22                 :            :     Initializable,
+      23                 :            :     ERC20Upgradeable,
+      24                 :            :     IERC20PermitUpgradeable,
+      25                 :            :     EIP712Upgradeable
+      26                 :            : {
+      27                 :            :     using CountersUpgradeable for CountersUpgradeable.Counter;
+      28                 :            : 
+      29                 :            :     mapping(address => CountersUpgradeable.Counter) private _nonces;
+      30                 :            : 
+      31                 :            :     // solhint-disable-next-line var-name-mixedcase
+      32                 :            :     bytes32 private constant _PERMIT_TYPEHASH =
+      33                 :            :         keccak256(
+      34                 :            :             "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
+      35                 :            :         );
+      36                 :            :     /**
+      37                 :            :      * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
+      38                 :            :      * However, to ensure consistency with the upgradeable transpiler, we will continue
+      39                 :            :      * to reserve a slot.
+      40                 :            :      * @custom:oz-renamed-from _PERMIT_TYPEHASH
+      41                 :            :      */
+      42                 :            :     // solhint-disable-next-line var-name-mixedcase
+      43                 :            :     bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;
+      44                 :            : 
+      45                 :            :     /**
+      46                 :            :      * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
+      47                 :            :      *
+      48                 :            :      * It's a good idea to use the same `name` that is defined as the ERC20 token name.
+      49                 :            :      */
+      50                 :            :     function __ERC20Permit_init(string memory name) internal onlyInitializing {
+      51                 :          0 :         __EIP712_init_unchained(name, "1");
+      52                 :            :     }
+      53                 :            : 
+      54                 :            :     function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {}
+      55                 :            : 
+      56                 :            :     /**
+      57                 :            :      * @dev See {IERC20Permit-permit}.
+      58                 :            :      */
+      59                 :            :     function permit(
+      60                 :            :         address owner,
+      61                 :            :         address spender,
+      62                 :            :         uint256 value,
+      63                 :            :         uint256 deadline,
+      64                 :            :         uint8 v,
+      65                 :            :         bytes32 r,
+      66                 :            :         bytes32 s
+      67                 :            :     ) public virtual override {
+      68         [ #  # ]:          0 :         require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
+      69                 :            : 
+      70                 :          0 :         bytes32 structHash = keccak256(
+      71                 :            :             abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)
+      72                 :            :         );
+      73                 :            : 
+      74                 :          0 :         bytes32 hash = _hashTypedDataV4(structHash);
+      75                 :            : 
+      76                 :          0 :         address signer = ECDSAUpgradeable.recover(hash, v, r, s);
+      77         [ #  # ]:          0 :         require(signer == owner, "ERC20Permit: invalid signature");
+      78                 :            : 
+      79                 :          0 :         _approve(owner, spender, value);
+      80                 :            :     }
+      81                 :            : 
+      82                 :            :     /**
+      83                 :            :      * @dev See {IERC20Permit-nonces}.
+      84                 :            :      */
+      85                 :            :     function nonces(address owner) public view virtual override returns (uint256) {
+      86                 :          0 :         return _nonces[owner].current();
+      87                 :            :     }
+      88                 :            : 
+      89                 :            :     /**
+      90                 :            :      * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
+      91                 :            :      */
+      92                 :            :     // solhint-disable-next-line func-name-mixedcase
+      93                 :            :     function DOMAIN_SEPARATOR() external view override returns (bytes32) {
+      94                 :          0 :         return _domainSeparatorV4();
+      95                 :            :     }
+      96                 :            : 
+      97                 :            :     /**
+      98                 :            :      * @dev "Consume a nonce": return the current value and increment.
+      99                 :            :      *
+     100                 :            :      * _Available since v4.1._
+     101                 :            :      */
+     102                 :            :     function _useNonce(address owner) internal virtual returns (uint256 current) {
+     103                 :          0 :         CountersUpgradeable.Counter storage nonce = _nonces[owner];
+     104                 :          0 :         current = nonce.current();
+     105                 :          0 :         nonce.increment();
+     106                 :            :     }
+     107                 :            : 
+     108                 :            :     /**
+     109                 :            :      * @dev This empty reserved space is put in place to allow future versions to add new
+     110                 :            :      * variables without shifting down storage in the inheritance chain.
+     111                 :            :      * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
+     112                 :            :      */
+     113                 :            :     uint256[49] private __gap;
+     114                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/GatewayMessageHandler.sol.func-sort-c.html b/coverage/libraries/gateway/GatewayMessageHandler.sol.func-sort-c.html new file mode 100644 index 0000000000..af32730962 --- /dev/null +++ b/coverage/libraries/gateway/GatewayMessageHandler.sol.func-sort-c.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - libraries/gateway/GatewayMessageHandler.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gateway - GatewayMessageHandler.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:060.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
GatewayMessageHandler.encodeFromL2GatewayMsg0
GatewayMessageHandler.encodeFromRouterToGateway0
GatewayMessageHandler.encodeToL2GatewayMsg0
GatewayMessageHandler.parseFromL1GatewayMsg0
GatewayMessageHandler.parseFromRouterToGateway0
GatewayMessageHandler.parseToL1GatewayMsg0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/GatewayMessageHandler.sol.func.html b/coverage/libraries/gateway/GatewayMessageHandler.sol.func.html new file mode 100644 index 0000000000..607dfaad28 --- /dev/null +++ b/coverage/libraries/gateway/GatewayMessageHandler.sol.func.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - libraries/gateway/GatewayMessageHandler.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gateway - GatewayMessageHandler.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:060.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
GatewayMessageHandler.encodeFromL2GatewayMsg0
GatewayMessageHandler.encodeFromRouterToGateway0
GatewayMessageHandler.encodeToL2GatewayMsg0
GatewayMessageHandler.parseFromL1GatewayMsg0
GatewayMessageHandler.parseFromRouterToGateway0
GatewayMessageHandler.parseToL1GatewayMsg0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/GatewayMessageHandler.sol.gcov.html b/coverage/libraries/gateway/GatewayMessageHandler.sol.gcov.html new file mode 100644 index 0000000000..5170d6e07c --- /dev/null +++ b/coverage/libraries/gateway/GatewayMessageHandler.sol.gcov.html @@ -0,0 +1,165 @@ + + + + + + + LCOV - lcov.info - libraries/gateway/GatewayMessageHandler.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gateway - GatewayMessageHandler.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:060.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : /// @notice this library manages encoding and decoding of gateway communication
+      22                 :            : library GatewayMessageHandler {
+      23                 :            :     // these are for communication from L1 to L2 gateway
+      24                 :            : 
+      25                 :            :     function encodeToL2GatewayMsg(bytes memory gatewayData, bytes memory callHookData)
+      26                 :            :         internal
+      27                 :            :         pure
+      28                 :            :         returns (bytes memory res)
+      29                 :            :     {
+      30                 :          0 :         res = abi.encode(gatewayData, callHookData);
+      31                 :            :     }
+      32                 :            : 
+      33                 :            :     function parseFromL1GatewayMsg(bytes calldata _data)
+      34                 :            :         internal
+      35                 :            :         pure
+      36                 :            :         returns (bytes memory gatewayData, bytes memory callHookData)
+      37                 :            :     {
+      38                 :            :         // abi decode may revert, but the encoding is done by L1 gateway, so we trust it
+      39                 :          0 :         (gatewayData, callHookData) = abi.decode(_data, (bytes, bytes));
+      40                 :            :     }
+      41                 :            : 
+      42                 :            :     // these are for communication from L2 to L1 gateway
+      43                 :            : 
+      44                 :            :     function encodeFromL2GatewayMsg(uint256 exitNum, bytes memory callHookData)
+      45                 :            :         internal
+      46                 :            :         pure
+      47                 :            :         returns (bytes memory res)
+      48                 :            :     {
+      49                 :          0 :         res = abi.encode(exitNum, callHookData);
+      50                 :            :     }
+      51                 :            : 
+      52                 :            :     function parseToL1GatewayMsg(bytes calldata _data)
+      53                 :            :         internal
+      54                 :            :         pure
+      55                 :            :         returns (uint256 exitNum, bytes memory callHookData)
+      56                 :            :     {
+      57                 :            :         // abi decode may revert, but the encoding is done by L1 gateway, so we trust it
+      58                 :          0 :         (exitNum, callHookData) = abi.decode(_data, (uint256, bytes));
+      59                 :            :     }
+      60                 :            : 
+      61                 :            :     // these are for communication from router to gateway
+      62                 :            : 
+      63                 :            :     function encodeFromRouterToGateway(address _from, bytes calldata _data)
+      64                 :            :         internal
+      65                 :            :         pure
+      66                 :            :         returns (bytes memory res)
+      67                 :            :     {
+      68                 :            :         // abi decode may revert, but the encoding is done by L1 gateway, so we trust it
+      69                 :          0 :         return abi.encode(_from, _data);
+      70                 :            :     }
+      71                 :            : 
+      72                 :            :     function parseFromRouterToGateway(bytes calldata _data)
+      73                 :            :         internal
+      74                 :            :         pure
+      75                 :            :         returns (address, bytes memory res)
+      76                 :            :     {
+      77                 :            :         // abi decode may revert, but the encoding is done by L1 gateway, so we trust it
+      78                 :          0 :         return abi.decode(_data, (address, bytes));
+      79                 :            :     }
+      80                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/GatewayRouter.sol.func-sort-c.html b/coverage/libraries/gateway/GatewayRouter.sol.func-sort-c.html new file mode 100644 index 0000000000..6f8b4138f6 --- /dev/null +++ b/coverage/libraries/gateway/GatewayRouter.sol.func-sort-c.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - libraries/gateway/GatewayRouter.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gateway - GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:102245.5 %
Date:2023-04-27 16:26:32Functions:2728.6 %
Branches:61060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
GatewayRouter.calculateL2TokenAddress0
GatewayRouter.finalizeInboundTransfer0
GatewayRouter.getGateway0
GatewayRouter.getOutboundCalldata0
GatewayRouter.outboundTransfer0
GatewayRouter.postUpgradeInit1
GatewayRouter._initialize4
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/GatewayRouter.sol.func.html b/coverage/libraries/gateway/GatewayRouter.sol.func.html new file mode 100644 index 0000000000..fc9fff1050 --- /dev/null +++ b/coverage/libraries/gateway/GatewayRouter.sol.func.html @@ -0,0 +1,109 @@ + + + + + + + LCOV - lcov.info - libraries/gateway/GatewayRouter.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gateway - GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:102245.5 %
Date:2023-04-27 16:26:32Functions:2728.6 %
Branches:61060.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
GatewayRouter._initialize4
GatewayRouter.calculateL2TokenAddress0
GatewayRouter.finalizeInboundTransfer0
GatewayRouter.getGateway0
GatewayRouter.getOutboundCalldata0
GatewayRouter.outboundTransfer0
GatewayRouter.postUpgradeInit1
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/GatewayRouter.sol.gcov.html b/coverage/libraries/gateway/GatewayRouter.sol.gcov.html new file mode 100644 index 0000000000..95b0a4082f --- /dev/null +++ b/coverage/libraries/gateway/GatewayRouter.sol.gcov.html @@ -0,0 +1,222 @@ + + + + + + + LCOV - lcov.info - libraries/gateway/GatewayRouter.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gateway - GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:102245.5 %
Date:2023-04-27 16:26:32Functions:2728.6 %
Branches:61060.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../ProxyUtil.sol";
+      22                 :            : import "@openzeppelin/contracts/utils/Address.sol";
+      23                 :            : import "./TokenGateway.sol";
+      24                 :            : import "./GatewayMessageHandler.sol";
+      25                 :            : import "./IGatewayRouter.sol";
+      26                 :            : 
+      27                 :            : /**
+      28                 :            :  * @title Common interface for L1 and L2 Gateway Routers
+      29                 :            :  */
+      30                 :            : abstract contract GatewayRouter is TokenGateway, IGatewayRouter {
+      31                 :            :     using Address for address;
+      32                 :            : 
+      33                 :            :     address internal constant ZERO_ADDR = address(0);
+      34                 :            :     address internal constant DISABLED = address(1);
+      35                 :            : 
+      36                 :            :     mapping(address => address) public l1TokenToGateway;
+      37                 :            :     address public override defaultGateway;
+      38                 :            : 
+      39                 :            :     function postUpgradeInit() external {
+      40                 :            :         // it is assumed the L2 Arbitrum Gateway contract is behind a Proxy controlled by a proxy admin
+      41                 :            :         // this function can only be called by the proxy admin contract
+      42                 :          1 :         address proxyAdmin = ProxyUtil.getProxyAdmin();
+      43         [ +  # ]:          1 :         require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");
+      44                 :            :         // this has no other logic since the current upgrade doesn't require this logic
+      45                 :            :     }
+      46                 :            : 
+      47                 :            :     function _initialize(
+      48                 :            :         address _counterpartGateway,
+      49                 :            :         address _router,
+      50                 :            :         address _defaultGateway
+      51                 :            :     ) internal {
+      52                 :            :         // if you are a router, you can't have a router
+      53         [ #  + ]:          4 :         require(_router == address(0), "BAD_ROUTER");
+      54                 :          4 :         TokenGateway._initialize(_counterpartGateway, _router);
+      55                 :            :         // default gateway can have 0 address
+      56                 :          2 :         defaultGateway = _defaultGateway;
+      57                 :            :     }
+      58                 :            : 
+      59                 :            :     function finalizeInboundTransfer(
+      60                 :            :         address, /* _token */
+      61                 :            :         address, /* _from */
+      62                 :            :         address, /* _to */
+      63                 :            :         uint256, /* _amount */
+      64                 :            :         bytes calldata /* _data */
+      65                 :            :     ) external payable virtual override {
+      66                 :          0 :         revert("ONLY_OUTBOUND_ROUTER");
+      67                 :            :     }
+      68                 :            : 
+      69                 :            :     function outboundTransfer(
+      70                 :            :         address _token,
+      71                 :            :         address _to,
+      72                 :            :         uint256 _amount,
+      73                 :            :         uint256 _maxGas,
+      74                 :            :         uint256 _gasPriceBid,
+      75                 :            :         bytes calldata _data
+      76                 :            :     ) public payable virtual override returns (bytes memory) {
+      77                 :            :         // this function is kept instead of delegating to outboundTransferCustomRefund to allow
+      78                 :            :         // compatibility with older gateways that did not implement outboundTransferCustomRefund
+      79                 :          0 :         address gateway = getGateway(_token);
+      80                 :          0 :         bytes memory gatewayData = GatewayMessageHandler.encodeFromRouterToGateway(
+      81                 :            :             msg.sender,
+      82                 :            :             _data
+      83                 :            :         );
+      84                 :            : 
+      85                 :          0 :         emit TransferRouted(_token, msg.sender, _to, gateway);
+      86                 :          0 :         return
+      87                 :            :             ITokenGateway(gateway).outboundTransfer{ value: msg.value }(
+      88                 :            :                 _token,
+      89                 :            :                 _to,
+      90                 :            :                 _amount,
+      91                 :            :                 _maxGas,
+      92                 :            :                 _gasPriceBid,
+      93                 :            :                 gatewayData
+      94                 :            :             );
+      95                 :            :     }
+      96                 :            : 
+      97                 :            :     function getOutboundCalldata(
+      98                 :            :         address _token,
+      99                 :            :         address _from,
+     100                 :            :         address _to,
+     101                 :            :         uint256 _amount,
+     102                 :            :         bytes memory _data
+     103                 :            :     ) public view virtual override returns (bytes memory) {
+     104                 :          0 :         address gateway = getGateway(_token);
+     105                 :          0 :         return TokenGateway(gateway).getOutboundCalldata(_token, _from, _to, _amount, _data);
+     106                 :            :     }
+     107                 :            : 
+     108                 :            :     function getGateway(address _token) public view virtual override returns (address gateway) {
+     109                 :          6 :         gateway = l1TokenToGateway[_token];
+     110                 :            : 
+     111         [ +  + ]:          6 :         if (gateway == ZERO_ADDR) {
+     112                 :            :             // if no gateway value set, use default gateway
+     113                 :          5 :             gateway = defaultGateway;
+     114                 :            :         }
+     115                 :            : 
+     116         [ +  + ]:          6 :         if (gateway == DISABLED || !gateway.isContract()) {
+     117                 :            :             // not a valid gateway
+     118                 :          5 :             return ZERO_ADDR;
+     119                 :            :         }
+     120                 :            : 
+     121                 :          0 :         return gateway;
+     122                 :            :     }
+     123                 :            : 
+     124                 :            :     function calculateL2TokenAddress(address l1ERC20)
+     125                 :            :         public
+     126                 :            :         view
+     127                 :            :         virtual
+     128                 :            :         override(TokenGateway, ITokenGateway)
+     129                 :            :         returns (address)
+     130                 :            :     {
+     131                 :          0 :         address gateway = getGateway(l1ERC20);
+     132         [ #  # ]:          0 :         if (gateway == ZERO_ADDR) {
+     133                 :          0 :             return ZERO_ADDR;
+     134                 :            :         }
+     135                 :          0 :         return TokenGateway(gateway).calculateL2TokenAddress(l1ERC20);
+     136                 :            :     }
+     137                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/TokenGateway.sol.func-sort-c.html b/coverage/libraries/gateway/TokenGateway.sol.func-sort-c.html new file mode 100644 index 0000000000..fba9552d4e --- /dev/null +++ b/coverage/libraries/gateway/TokenGateway.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - libraries/gateway/TokenGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gateway - TokenGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2023-04-27 16:26:32Functions:22100.0 %
Branches:44100.0 %
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TokenGateway._initialize17
TokenGateway.isRouter22
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/TokenGateway.sol.func.html b/coverage/libraries/gateway/TokenGateway.sol.func.html new file mode 100644 index 0000000000..815c17f53b --- /dev/null +++ b/coverage/libraries/gateway/TokenGateway.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - libraries/gateway/TokenGateway.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gateway - TokenGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2023-04-27 16:26:32Functions:22100.0 %
Branches:44100.0 %
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TokenGateway._initialize17
TokenGateway.isRouter22
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/TokenGateway.sol.gcov.html b/coverage/libraries/gateway/TokenGateway.sol.gcov.html new file mode 100644 index 0000000000..af146ceb04 --- /dev/null +++ b/coverage/libraries/gateway/TokenGateway.sol.gcov.html @@ -0,0 +1,148 @@ + + + + + + + LCOV - lcov.info - libraries/gateway/TokenGateway.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gateway - TokenGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2023-04-27 16:26:32Functions:22100.0 %
Branches:44100.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./ITokenGateway.sol";
+      22                 :            : import "@openzeppelin/contracts/utils/Address.sol";
+      23                 :            : 
+      24                 :            : abstract contract TokenGateway is ITokenGateway {
+      25                 :            :     using Address for address;
+      26                 :            : 
+      27                 :            :     address public counterpartGateway;
+      28                 :            :     address public router;
+      29                 :            : 
+      30                 :            :     // This modifier is overriden in gateways to validate the message sender
+      31                 :            :     // For L1 to L2 messages need to be validated against the aliased counterpartGateway
+      32                 :            :     // For L2 to L1 messages need to be validated against the bridge and L2ToL1Sender
+      33                 :            :     // prettier-ignore
+      34                 :            :     modifier onlyCounterpartGateway() virtual;
+      35                 :            : 
+      36                 :            :     function _initialize(address _counterpartGateway, address _router) internal virtual {
+      37                 :            :         // This initializes internal variables of the abstract contract it can be chained together with other functions.
+      38                 :            :         // It is virtual so subclasses can override or wrap around this logic.
+      39                 :            :         // An example where this is useful is different subclasses that validate the router address differently
+      40         [ +  + ]:         17 :         require(_counterpartGateway != address(0), "INVALID_COUNTERPART");
+      41         [ +  + ]:         16 :         require(counterpartGateway == address(0), "ALREADY_INIT");
+      42                 :         15 :         counterpartGateway = _counterpartGateway;
+      43                 :         15 :         router = _router;
+      44                 :            :     }
+      45                 :            : 
+      46                 :            :     function isRouter(address _target) internal view returns (bool isTargetRouter) {
+      47                 :         22 :         return _target == router;
+      48                 :            :     }
+      49                 :            : 
+      50                 :            :     /**
+      51                 :            :      * @notice Calculate the address used when bridging an ERC20 token
+      52                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
+      53                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
+      54                 :            :      * @param l1ERC20 address of L1 token
+      55                 :            :      * @return L2 address of a bridged ERC20 token
+      56                 :            :      */
+      57                 :            :     function calculateL2TokenAddress(address l1ERC20)
+      58                 :            :         public
+      59                 :            :         view
+      60                 :            :         virtual
+      61                 :            :         override
+      62                 :            :         returns (address);
+      63                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/index-sort-b.html b/coverage/libraries/gateway/index-sort-b.html new file mode 100644 index 0000000000..90ff9d03f8 --- /dev/null +++ b/coverage/libraries/gateway/index-sort-b.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - libraries/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gatewayHitTotalCoverage
Test:lcov.infoLines:153345.5 %
Date:2023-04-27 16:26:32Functions:41526.7 %
Branches:101471.4 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
GatewayRouter.sol +
45.5%45.5%
+
45.5 %10 / 2228.6 %2 / 760.0 %6 / 10
GatewayMessageHandler.sol +
0.0%
+
0.0 %0 / 60.0 %0 / 6-0 / 0
TokenGateway.sol +
100.0%
+
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/index-sort-f.html b/coverage/libraries/gateway/index-sort-f.html new file mode 100644 index 0000000000..47ad0978d8 --- /dev/null +++ b/coverage/libraries/gateway/index-sort-f.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - libraries/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gatewayHitTotalCoverage
Test:lcov.infoLines:153345.5 %
Date:2023-04-27 16:26:32Functions:41526.7 %
Branches:101471.4 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
GatewayMessageHandler.sol +
0.0%
+
0.0 %0 / 60.0 %0 / 6-0 / 0
GatewayRouter.sol +
45.5%45.5%
+
45.5 %10 / 2228.6 %2 / 760.0 %6 / 10
TokenGateway.sol +
100.0%
+
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/index-sort-l.html b/coverage/libraries/gateway/index-sort-l.html new file mode 100644 index 0000000000..9fd98ab3a6 --- /dev/null +++ b/coverage/libraries/gateway/index-sort-l.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - libraries/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gatewayHitTotalCoverage
Test:lcov.infoLines:153345.5 %
Date:2023-04-27 16:26:32Functions:41526.7 %
Branches:101471.4 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
GatewayMessageHandler.sol +
0.0%
+
0.0 %0 / 60.0 %0 / 6-0 / 0
GatewayRouter.sol +
45.5%45.5%
+
45.5 %10 / 2228.6 %2 / 760.0 %6 / 10
TokenGateway.sol +
100.0%
+
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/gateway/index.html b/coverage/libraries/gateway/index.html new file mode 100644 index 0000000000..524b0fbd10 --- /dev/null +++ b/coverage/libraries/gateway/index.html @@ -0,0 +1,131 @@ + + + + + + + LCOV - lcov.info - libraries/gateway + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - libraries/gatewayHitTotalCoverage
Test:lcov.infoLines:153345.5 %
Date:2023-04-27 16:26:32Functions:41526.7 %
Branches:101471.4 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
GatewayMessageHandler.sol +
0.0%
+
0.0 %0 / 60.0 %0 / 6-0 / 0
GatewayRouter.sol +
45.5%45.5%
+
45.5 %10 / 2228.6 %2 / 760.0 %6 / 10
TokenGateway.sol +
100.0%
+
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/index-sort-b.html b/coverage/libraries/index-sort-b.html new file mode 100644 index 0000000000..c4353c6972 --- /dev/null +++ b/coverage/libraries/index-sort-b.html @@ -0,0 +1,275 @@ + + + + + + + LCOV - lcov.info - libraries + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - librariesHitTotalCoverage
Test:lcov.infoLines:3917022.9 %
Date:2023-04-27 16:26:32Functions:146222.6 %
Branches:106415.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
Cloneable.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 20.0 %0 / 2
TransferAndCallToken.sol +
0.0%
+
0.0 %0 / 100.0 %0 / 30.0 %0 / 2
L2GatewayToken.sol +
0.0%
+
0.0 %0 / 70.0 %0 / 30.0 %0 / 4
Whitelist.sol +
0.0%
+
0.0 %0 / 110.0 %0 / 40.0 %0 / 4
ClonableBeaconProxy.sol +
0.0%
+
0.0 %0 / 100.0 %0 / 40.0 %0 / 4
aeWETH.sol +
0.0%
+
0.0 %0 / 110.0 %0 / 70.0 %0 / 4
draft-ERC20PermitUpgradeable.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 60.0 %0 / 4
BytesLib.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 40.0 %0 / 8
BytesParser.sol +
0.0%
+
0.0 %0 / 210.0 %0 / 20.0 %0 / 10
ERC20Upgradeable.sol +
63.3%63.3%
+
63.3 %38 / 6061.9 %13 / 2145.5 %10 / 22
L2CustomGatewayToken.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
ERC165.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
ProxyUtil.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 1-0 / 0
AddressAliasHelper.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
aeERC20.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/index-sort-f.html b/coverage/libraries/index-sort-f.html new file mode 100644 index 0000000000..71c882d694 --- /dev/null +++ b/coverage/libraries/index-sort-f.html @@ -0,0 +1,275 @@ + + + + + + + LCOV - lcov.info - libraries + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - librariesHitTotalCoverage
Test:lcov.infoLines:3917022.9 %
Date:2023-04-27 16:26:32Functions:146222.6 %
Branches:106415.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2CustomGatewayToken.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
ProxyUtil.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 1-0 / 0
aeERC20.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 1-0 / 0
BytesParser.sol +
0.0%
+
0.0 %0 / 210.0 %0 / 20.0 %0 / 10
Cloneable.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 20.0 %0 / 2
AddressAliasHelper.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
L2GatewayToken.sol +
0.0%
+
0.0 %0 / 70.0 %0 / 30.0 %0 / 4
TransferAndCallToken.sol +
0.0%
+
0.0 %0 / 100.0 %0 / 30.0 %0 / 2
BytesLib.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 40.0 %0 / 8
Whitelist.sol +
0.0%
+
0.0 %0 / 110.0 %0 / 40.0 %0 / 4
ClonableBeaconProxy.sol +
0.0%
+
0.0 %0 / 100.0 %0 / 40.0 %0 / 4
draft-ERC20PermitUpgradeable.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 60.0 %0 / 4
aeWETH.sol +
0.0%
+
0.0 %0 / 110.0 %0 / 70.0 %0 / 4
ERC20Upgradeable.sol +
63.3%63.3%
+
63.3 %38 / 6061.9 %13 / 2145.5 %10 / 22
ERC165.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/index-sort-l.html b/coverage/libraries/index-sort-l.html new file mode 100644 index 0000000000..3bc996c03a --- /dev/null +++ b/coverage/libraries/index-sort-l.html @@ -0,0 +1,275 @@ + + + + + + + LCOV - lcov.info - libraries + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - librariesHitTotalCoverage
Test:lcov.infoLines:3917022.9 %
Date:2023-04-27 16:26:32Functions:146222.6 %
Branches:106415.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2CustomGatewayToken.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
ProxyUtil.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 1-0 / 0
AddressAliasHelper.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
Cloneable.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 20.0 %0 / 2
aeERC20.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 1-0 / 0
L2GatewayToken.sol +
0.0%
+
0.0 %0 / 70.0 %0 / 30.0 %0 / 4
TransferAndCallToken.sol +
0.0%
+
0.0 %0 / 100.0 %0 / 30.0 %0 / 2
ClonableBeaconProxy.sol +
0.0%
+
0.0 %0 / 100.0 %0 / 40.0 %0 / 4
Whitelist.sol +
0.0%
+
0.0 %0 / 110.0 %0 / 40.0 %0 / 4
aeWETH.sol +
0.0%
+
0.0 %0 / 110.0 %0 / 70.0 %0 / 4
draft-ERC20PermitUpgradeable.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 60.0 %0 / 4
BytesLib.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 40.0 %0 / 8
BytesParser.sol +
0.0%
+
0.0 %0 / 210.0 %0 / 20.0 %0 / 10
ERC20Upgradeable.sol +
63.3%63.3%
+
63.3 %38 / 6061.9 %13 / 2145.5 %10 / 22
ERC165.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/libraries/index.html b/coverage/libraries/index.html new file mode 100644 index 0000000000..020bffaaab --- /dev/null +++ b/coverage/libraries/index.html @@ -0,0 +1,275 @@ + + + + + + + LCOV - lcov.info - libraries + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - librariesHitTotalCoverage
Test:lcov.infoLines:3917022.9 %
Date:2023-04-27 16:26:32Functions:146222.6 %
Branches:106415.6 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
AddressAliasHelper.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
BytesLib.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 40.0 %0 / 8
BytesParser.sol +
0.0%
+
0.0 %0 / 210.0 %0 / 20.0 %0 / 10
ClonableBeaconProxy.sol +
0.0%
+
0.0 %0 / 100.0 %0 / 40.0 %0 / 4
Cloneable.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 20.0 %0 / 2
ERC165.sol +
100.0%
+
100.0 %1 / 1100.0 %1 / 1-0 / 0
ERC20Upgradeable.sol +
63.3%63.3%
+
63.3 %38 / 6061.9 %13 / 2145.5 %10 / 22
L2CustomGatewayToken.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
L2GatewayToken.sol +
0.0%
+
0.0 %0 / 70.0 %0 / 30.0 %0 / 4
ProxyUtil.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 1-0 / 0
TransferAndCallToken.sol +
0.0%
+
0.0 %0 / 100.0 %0 / 30.0 %0 / 2
Whitelist.sol +
0.0%
+
0.0 %0 / 110.0 %0 / 40.0 %0 / 4
aeERC20.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 1-0 / 0
aeWETH.sol +
0.0%
+
0.0 %0 / 110.0 %0 / 70.0 %0 / 4
draft-ERC20PermitUpgradeable.sol +
0.0%
+
0.0 %0 / 120.0 %0 / 60.0 %0 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/ruby.png b/coverage/ruby.png new file mode 100644 index 0000000000000000000000000000000000000000..991b6d4ec9e78be165e3ef757eed1aada287364d GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^FceV#7`HfI^%F z9+AZi4BSE>%y{W;-5;PJOS+@4BLl<6e(pbstUx|nfKQ0)e^Y%R^MdiLxj>4`)5S5Q b;#P73kj=!v_*DHKNFRfztDnm{r-UW|iOwIS literal 0 HcmV?d00001 diff --git a/coverage/snow.png b/coverage/snow.png new file mode 100644 index 0000000000000000000000000000000000000000..2cdae107fceec6e7f02ac7acb4a34a82a540caa5 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^MM!lvI6;R0X`wF|Ns97GD8ntt^-nBo-U3d c6}OTTfNUlP#;5A{K>8RwUHx3vIVCg!071?oo&W#< literal 0 HcmV?d00001 diff --git a/coverage/test/AddressMappingTest.sol.func-sort-c.html b/coverage/test/AddressMappingTest.sol.func-sort-c.html new file mode 100644 index 0000000000..4214503e36 --- /dev/null +++ b/coverage/test/AddressMappingTest.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - test/AddressMappingTest.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - AddressMappingTest.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
AddressMappingTest.getL1AddressTest0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/AddressMappingTest.sol.func.html b/coverage/test/AddressMappingTest.sol.func.html new file mode 100644 index 0000000000..89167466cb --- /dev/null +++ b/coverage/test/AddressMappingTest.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - test/AddressMappingTest.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - AddressMappingTest.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
AddressMappingTest.getL1AddressTest0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/AddressMappingTest.sol.gcov.html b/coverage/test/AddressMappingTest.sol.gcov.html new file mode 100644 index 0000000000..d8877e7636 --- /dev/null +++ b/coverage/test/AddressMappingTest.sol.gcov.html @@ -0,0 +1,113 @@ + + + + + + + LCOV - lcov.info - test/AddressMappingTest.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - AddressMappingTest.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../arbitrum/L2ArbitrumMessenger.sol";
+      22                 :            : import "../libraries/AddressAliasHelper.sol";
+      23                 :            : 
+      24                 :            : contract AddressMappingTest is L2ArbitrumMessenger {
+      25                 :            :     function getL1AddressTest(address sender) external pure returns (address l1Address) {
+      26                 :          0 :         return AddressAliasHelper.undoL1ToL2Alias(sender);
+      27                 :            :     }
+      28                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/ArbSysMock.sol.func-sort-c.html b/coverage/test/ArbSysMock.sol.func-sort-c.html new file mode 100644 index 0000000000..64784621e3 --- /dev/null +++ b/coverage/test/ArbSysMock.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - test/ArbSysMock.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - ArbSysMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ArbSysMock.sendTxToL10
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/ArbSysMock.sol.func.html b/coverage/test/ArbSysMock.sol.func.html new file mode 100644 index 0000000000..3652783755 --- /dev/null +++ b/coverage/test/ArbSysMock.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - test/ArbSysMock.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - ArbSysMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ArbSysMock.sendTxToL10
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/ArbSysMock.sol.gcov.html b/coverage/test/ArbSysMock.sol.gcov.html new file mode 100644 index 0000000000..30477be16d --- /dev/null +++ b/coverage/test/ArbSysMock.sol.gcov.html @@ -0,0 +1,102 @@ + + + + + + + LCOV - lcov.info - test/ArbSysMock.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - ArbSysMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : pragma solidity ^0.8.0;
+       2                 :            : 
+       3                 :            : contract ArbSysMock {
+       4                 :            :     event ArbSysL2ToL1Tx(address from, address to, uint256 value, bytes data);
+       5                 :            :     uint256 counter;
+       6                 :            : 
+       7                 :            :     function sendTxToL1(address destination, bytes calldata calldataForL1)
+       8                 :            :         external
+       9                 :            :         payable
+      10                 :            :         returns (uint256 exitNum)
+      11                 :            :     {
+      12                 :          0 :         exitNum = counter;
+      13                 :          0 :         counter = exitNum + 1;
+      14                 :          0 :         emit ArbSysL2ToL1Tx(msg.sender, destination, msg.value, calldataForL1);
+      15                 :          0 :         return exitNum;
+      16                 :            :     }
+      17                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/InboxMock.sol.func-sort-c.html b/coverage/test/InboxMock.sol.func-sort-c.html new file mode 100644 index 0000000000..ab174d644f --- /dev/null +++ b/coverage/test/InboxMock.sol.func-sort-c.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test/InboxMock.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - InboxMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:141687.5 %
Date:2023-04-27 16:26:32Functions:66100.0 %
Branches:2450.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
ERC20InboxMock.createRetryableTicket2
AbsInboxMock.activeOutbox4
AbsInboxMock.l2ToL1Sender4
AbsInboxMock.setL2ToL1Sender4
AbsInboxMock.bridge14
InboxMock.createRetryableTicket15
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/InboxMock.sol.func.html b/coverage/test/InboxMock.sol.func.html new file mode 100644 index 0000000000..ed8d207424 --- /dev/null +++ b/coverage/test/InboxMock.sol.func.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test/InboxMock.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - InboxMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:141687.5 %
Date:2023-04-27 16:26:32Functions:66100.0 %
Branches:2450.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
AbsInboxMock.activeOutbox4
AbsInboxMock.bridge14
AbsInboxMock.l2ToL1Sender4
AbsInboxMock.setL2ToL1Sender4
ERC20InboxMock.createRetryableTicket2
InboxMock.createRetryableTicket15
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/InboxMock.sol.gcov.html b/coverage/test/InboxMock.sol.gcov.html new file mode 100644 index 0000000000..865902d45c --- /dev/null +++ b/coverage/test/InboxMock.sol.gcov.html @@ -0,0 +1,194 @@ + + + + + + + LCOV - lcov.info - test/InboxMock.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - InboxMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:141687.5 %
Date:2023-04-27 16:26:32Functions:66100.0 %
Branches:2450.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol";
+      22                 :            : import "@arbitrum/nitro-contracts/src/bridge/IBridge.sol";
+      23                 :            : 
+      24                 :            : abstract contract AbsInboxMock {
+      25                 :            :     address l2ToL1SenderMock = address(0);
+      26                 :            : 
+      27                 :            :     event TicketData(uint256 maxSubmissionCost);
+      28                 :            :     event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress);
+      29                 :            :     event InboxRetryableTicket(address from, address to, uint256 value, uint256 maxGas, bytes data);
+      30                 :            : 
+      31                 :            :     function bridge() external view returns (IBridge) {
+      32                 :         14 :         return IBridge(address(this));
+      33                 :            :     }
+      34                 :            : 
+      35                 :            :     function activeOutbox() external view returns (address) {
+      36                 :          4 :         return address(this);
+      37                 :            :     }
+      38                 :            : 
+      39                 :            :     function setL2ToL1Sender(address sender) external {
+      40                 :          4 :         l2ToL1SenderMock = sender;
+      41                 :            :     }
+      42                 :            : 
+      43                 :            :     function l2ToL1Sender() external view returns (address) {
+      44                 :          4 :         return l2ToL1SenderMock;
+      45                 :            :     }
+      46                 :            : }
+      47                 :            : 
+      48                 :            : contract InboxMock is AbsInboxMock {
+      49                 :            :     function createRetryableTicket(
+      50                 :            :         address to,
+      51                 :            :         uint256 l2CallValue,
+      52                 :            :         uint256 maxSubmissionCost,
+      53                 :            :         address excessFeeRefundAddress,
+      54                 :            :         address callValueRefundAddress,
+      55                 :            :         uint256 gasLimit,
+      56                 :            :         uint256 maxFeePerGas,
+      57                 :            :         bytes calldata data
+      58                 :            :     ) external payable returns (uint256) {
+      59         [ #  + ]:         15 :         if (msg.value < (maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas)) {
+      60                 :          0 :             revert("WRONG_ETH_VALUE");
+      61                 :            :         }
+      62                 :         15 :         emit TicketData(maxSubmissionCost);
+      63                 :         15 :         emit RefundAddresses(excessFeeRefundAddress, callValueRefundAddress);
+      64                 :         15 :         emit InboxRetryableTicket(msg.sender, to, l2CallValue, gasLimit, data);
+      65                 :         15 :         return 0;
+      66                 :            :     }
+      67                 :            : }
+      68                 :            : 
+      69                 :            : contract ERC20InboxMock is AbsInboxMock {
+      70                 :            :     event ERC20InboxRetryableTicket(
+      71                 :            :         address from,
+      72                 :            :         address to,
+      73                 :            :         uint256 l2CallValue,
+      74                 :            :         uint256 maxGas,
+      75                 :            :         uint256 gasPrice,
+      76                 :            :         uint256 tokenTotalFeeAmount,
+      77                 :            :         bytes data
+      78                 :            :     );
+      79                 :            : 
+      80                 :            :     function createRetryableTicket(
+      81                 :            :         address to,
+      82                 :            :         uint256 l2CallValue,
+      83                 :            :         uint256 maxSubmissionCost,
+      84                 :            :         address excessFeeRefundAddress,
+      85                 :            :         address callValueRefundAddress,
+      86                 :            :         uint256 gasLimit,
+      87                 :            :         uint256 maxFeePerGas,
+      88                 :            :         uint256 tokenTotalFeeAmount,
+      89                 :            :         bytes calldata data
+      90                 :            :     ) external returns (uint256) {
+      91                 :            :         // ensure the user's deposit alone will make submission succeed
+      92         [ #  + ]:          2 :         if (tokenTotalFeeAmount < (maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas)) {
+      93                 :          0 :             revert("WRONG_TOKEN_VALUE");
+      94                 :            :         }
+      95                 :            : 
+      96                 :          2 :         emit TicketData(maxSubmissionCost);
+      97                 :          2 :         emit RefundAddresses(excessFeeRefundAddress, callValueRefundAddress);
+      98                 :          2 :         emit ERC20InboxRetryableTicket(
+      99                 :            :             msg.sender,
+     100                 :            :             to,
+     101                 :            :             l2CallValue,
+     102                 :            :             gasLimit,
+     103                 :            :             maxFeePerGas,
+     104                 :            :             tokenTotalFeeAmount,
+     105                 :            :             data
+     106                 :            :         );
+     107                 :          2 :         return 0;
+     108                 :            :     }
+     109                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestArbCustomToken.sol.func-sort-c.html b/coverage/test/TestArbCustomToken.sol.func-sort-c.html new file mode 100644 index 0000000000..f4043751fe --- /dev/null +++ b/coverage/test/TestArbCustomToken.sol.func-sort-c.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test/TestArbCustomToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestArbCustomToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
MintableTestArbCustomToken.userMint0
ReverseTestArbCustomToken.mint0
ReverseTestArbCustomToken.someWackyCustomStuff0
TestArbCustomToken.bridgeBurn0
TestArbCustomToken.bridgeMint0
TestArbCustomToken.someWackyCustomStuff0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestArbCustomToken.sol.func.html b/coverage/test/TestArbCustomToken.sol.func.html new file mode 100644 index 0000000000..e346ea2b88 --- /dev/null +++ b/coverage/test/TestArbCustomToken.sol.func.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test/TestArbCustomToken.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestArbCustomToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
MintableTestArbCustomToken.userMint0
ReverseTestArbCustomToken.mint0
ReverseTestArbCustomToken.someWackyCustomStuff0
TestArbCustomToken.bridgeBurn0
TestArbCustomToken.bridgeMint0
TestArbCustomToken.someWackyCustomStuff0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestArbCustomToken.sol.gcov.html b/coverage/test/TestArbCustomToken.sol.gcov.html new file mode 100644 index 0000000000..306e54285f --- /dev/null +++ b/coverage/test/TestArbCustomToken.sol.gcov.html @@ -0,0 +1,164 @@ + + + + + + + LCOV - lcov.info - test/TestArbCustomToken.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestArbCustomToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../arbitrum/IArbToken.sol";
+      22                 :            : import "../arbitrum/ReverseArbToken.sol";
+      23                 :            : import "../libraries/aeERC20.sol";
+      24                 :            : 
+      25                 :            : contract TestArbCustomToken is aeERC20, IArbToken {
+      26                 :            :     address public l2Gateway;
+      27                 :            :     address public override l1Address;
+      28                 :            : 
+      29                 :            :     modifier onlyGateway() {
+      30                 :            :         require(msg.sender == l2Gateway, "ONLY_l2GATEWAY");
+      31                 :            :         _;
+      32                 :            :     }
+      33                 :            : 
+      34                 :            :     constructor(address _l2Gateway, address _l1Address) {
+      35                 :            :         l2Gateway = _l2Gateway;
+      36                 :            :         l1Address = _l1Address;
+      37                 :            :         aeERC20._initialize("TestCustomToken", "CARB", uint8(18));
+      38                 :            :     }
+      39                 :            : 
+      40                 :            :     function someWackyCustomStuff() public {}
+      41                 :            : 
+      42                 :            :     function bridgeMint(address account, uint256 amount) external virtual override onlyGateway {
+      43                 :          0 :         _mint(account, amount);
+      44                 :            :     }
+      45                 :            : 
+      46                 :            :     function bridgeBurn(address account, uint256 amount) external virtual override onlyGateway {
+      47                 :          0 :         _burn(account, amount);
+      48                 :            :     }
+      49                 :            : }
+      50                 :            : 
+      51                 :            : contract MintableTestArbCustomToken is TestArbCustomToken {
+      52                 :            :     constructor(address _l2Gateway, address _l1Address) TestArbCustomToken(_l2Gateway, _l1Address){}
+      53                 :            : 
+      54                 :            :     function userMint(address account, uint256 amount) external {
+      55                 :          0 :         _mint(account, amount);
+      56                 :            :     }
+      57                 :            : }
+      58                 :            : 
+      59                 :            : contract ReverseTestArbCustomToken is aeERC20, IArbToken, ReverseArbToken {
+      60                 :            :     address public l2Gateway;
+      61                 :            :     address public override l1Address;
+      62                 :            : 
+      63                 :            :     modifier onlyGateway() {
+      64                 :            :         require(msg.sender == l2Gateway, "ONLY_l2GATEWAY");
+      65                 :            :         _;
+      66                 :            :     }
+      67                 :            : 
+      68                 :            :     constructor(address _l2Gateway, address _l1Address) {
+      69                 :            :         l2Gateway = _l2Gateway;
+      70                 :            :         l1Address = _l1Address;
+      71                 :            :         aeERC20._initialize("TestReverseCustomToken", "RARB", uint8(18));
+      72                 :            :     }
+      73                 :            : 
+      74                 :            :     function someWackyCustomStuff() public {}
+      75                 :            : 
+      76                 :            :     function mint() external {
+      77                 :          0 :         _mint(msg.sender, 50000000);
+      78                 :            :     }
+      79                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestArbCustomTokenBurnFee.sol.func-sort-c.html b/coverage/test/TestArbCustomTokenBurnFee.sol.func-sort-c.html new file mode 100644 index 0000000000..4135ebf1c4 --- /dev/null +++ b/coverage/test/TestArbCustomTokenBurnFee.sol.func-sort-c.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - test/TestArbCustomTokenBurnFee.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestArbCustomTokenBurnFee.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TestArbCustomTokenBurnFee._burn0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestArbCustomTokenBurnFee.sol.func.html b/coverage/test/TestArbCustomTokenBurnFee.sol.func.html new file mode 100644 index 0000000000..e6e96637c7 --- /dev/null +++ b/coverage/test/TestArbCustomTokenBurnFee.sol.func.html @@ -0,0 +1,85 @@ + + + + + + + LCOV - lcov.info - test/TestArbCustomTokenBurnFee.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestArbCustomTokenBurnFee.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ +
+ + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TestArbCustomTokenBurnFee._burn0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestArbCustomTokenBurnFee.sol.gcov.html b/coverage/test/TestArbCustomTokenBurnFee.sol.gcov.html new file mode 100644 index 0000000000..19090fe970 --- /dev/null +++ b/coverage/test/TestArbCustomTokenBurnFee.sol.gcov.html @@ -0,0 +1,120 @@ + + + + + + + LCOV - lcov.info - test/TestArbCustomTokenBurnFee.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestArbCustomTokenBurnFee.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "./TestArbCustomToken.sol";
+      22                 :            : 
+      23                 :            : contract TestArbCustomTokenBurnFee is TestArbCustomToken {
+      24                 :            :     constructor(
+      25                 :            :         address _l2Gateway,
+      26                 :            :         address _l1Address
+      27                 :            :     ) TestArbCustomToken(_l2Gateway, _l1Address) {}
+      28                 :            : 
+      29                 :            :     // this token transfer extra 1 wei from the sender as fee when it burn token
+      30                 :            :     // alternatively, it can also be a callback that pass execution to the user
+      31                 :            :     function _burn(address account, uint256 amount) internal override {
+      32                 :          0 :         super._burn(account, amount);
+      33                 :          0 :         _transfer(account, address(1), 1);
+      34                 :            :     }
+      35                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestBytesParser.sol.func-sort-c.html b/coverage/test/TestBytesParser.sol.func-sort-c.html new file mode 100644 index 0000000000..24ddc1b499 --- /dev/null +++ b/coverage/test/TestBytesParser.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - test/TestBytesParser.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestBytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TestBytesParser.bytesToString0
TestBytesParser.bytesToUint80
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestBytesParser.sol.func.html b/coverage/test/TestBytesParser.sol.func.html new file mode 100644 index 0000000000..2203ea8f31 --- /dev/null +++ b/coverage/test/TestBytesParser.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - test/TestBytesParser.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestBytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TestBytesParser.bytesToString0
TestBytesParser.bytesToUint80
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestBytesParser.sol.gcov.html b/coverage/test/TestBytesParser.sol.gcov.html new file mode 100644 index 0000000000..beffbc48e6 --- /dev/null +++ b/coverage/test/TestBytesParser.sol.gcov.html @@ -0,0 +1,120 @@ + + + + + + + LCOV - lcov.info - test/TestBytesParser.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestBytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../libraries/BytesParser.sol";
+      22                 :            : 
+      23                 :            : contract TestBytesParser {
+      24                 :            :     function bytesToString(bytes memory input)
+      25                 :            :         public
+      26                 :            :         pure
+      27                 :            :         returns (bool success, string memory res)
+      28                 :            :     {
+      29                 :          0 :         return BytesParser.toString(input);
+      30                 :            :     }
+      31                 :            : 
+      32                 :            :     function bytesToUint8(bytes memory input) public pure returns (bool, uint8) {
+      33                 :          0 :         return BytesParser.toUint8(input);
+      34                 :            :     }
+      35                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestCustomTokenL1.sol.func-sort-c.html b/coverage/test/TestCustomTokenL1.sol.func-sort-c.html new file mode 100644 index 0000000000..6f64c2488e --- /dev/null +++ b/coverage/test/TestCustomTokenL1.sol.func-sort-c.html @@ -0,0 +1,125 @@ + + + + + + + LCOV - lcov.info - test/TestCustomTokenL1.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestCustomTokenL1.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:0110.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
MintableTestCustomTokenL1.balanceOf0
MintableTestCustomTokenL1.bridgeMint0
MintableTestCustomTokenL1.transferFrom0
ReverseTestCustomTokenL1.balanceOf0
ReverseTestCustomTokenL1.bridgeBurn0
ReverseTestCustomTokenL1.transferFrom0
TestCustomTokenL1.balanceOf0
TestCustomTokenL1.isArbitrumEnabled0
TestCustomTokenL1.mint0
TestCustomTokenL1.registerTokenOnL20
TestCustomTokenL1.transferFrom0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestCustomTokenL1.sol.func.html b/coverage/test/TestCustomTokenL1.sol.func.html new file mode 100644 index 0000000000..a85935a0a5 --- /dev/null +++ b/coverage/test/TestCustomTokenL1.sol.func.html @@ -0,0 +1,125 @@ + + + + + + + LCOV - lcov.info - test/TestCustomTokenL1.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestCustomTokenL1.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:0110.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
MintableTestCustomTokenL1.balanceOf0
MintableTestCustomTokenL1.bridgeMint0
MintableTestCustomTokenL1.transferFrom0
ReverseTestCustomTokenL1.balanceOf0
ReverseTestCustomTokenL1.bridgeBurn0
ReverseTestCustomTokenL1.transferFrom0
TestCustomTokenL1.balanceOf0
TestCustomTokenL1.isArbitrumEnabled0
TestCustomTokenL1.mint0
TestCustomTokenL1.registerTokenOnL20
TestCustomTokenL1.transferFrom0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestCustomTokenL1.sol.gcov.html b/coverage/test/TestCustomTokenL1.sol.gcov.html new file mode 100644 index 0000000000..21d54bd954 --- /dev/null +++ b/coverage/test/TestCustomTokenL1.sol.gcov.html @@ -0,0 +1,253 @@ + + + + + + + LCOV - lcov.info - test/TestCustomTokenL1.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestCustomTokenL1.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:0110.0 %
Branches:020.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.0;
+       4                 :            : 
+       5                 :            : import "../libraries/aeERC20.sol";
+       6                 :            : import "../ethereum/ICustomToken.sol";
+       7                 :            : import "../ethereum/gateway/L1CustomGateway.sol";
+       8                 :            : import "../ethereum/gateway/L1GatewayRouter.sol";
+       9                 :            : import "@openzeppelin/contracts/utils/Context.sol";
+      10                 :            : import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
+      11                 :            : 
+      12                 :            : interface IL1CustomGateway {
+      13                 :            :     function registerTokenToL2(
+      14                 :            :         address _l2Address,
+      15                 :            :         uint256 _maxGas,
+      16                 :            :         uint256 _gasPriceBid,
+      17                 :            :         uint256 _maxSubmissionCost,
+      18                 :            :         address _creditBackAddress
+      19                 :            :     ) external payable returns (uint256);
+      20                 :            : }
+      21                 :            : 
+      22                 :            : interface IGatewayRouter2 {
+      23                 :            :     function setGateway(
+      24                 :            :         address _gateway,
+      25                 :            :         uint256 _maxGas,
+      26                 :            :         uint256 _gasPriceBid,
+      27                 :            :         uint256 _maxSubmissionCost,
+      28                 :            :         address _creditBackAddress
+      29                 :            :     ) external payable returns (uint256);
+      30                 :            : }
+      31                 :            : 
+      32                 :            : contract TestCustomTokenL1 is aeERC20, ICustomToken {
+      33                 :            :     address public gateway;
+      34                 :            :     address public router;
+      35                 :            :     bool private shouldRegisterGateway;
+      36                 :            : 
+      37                 :            :     constructor(address _gateway, address _router) {
+      38                 :            :         gateway = _gateway;
+      39                 :            :         router = _router;
+      40                 :            :         aeERC20._initialize("TestCustomToken", "CARB", uint8(18));
+      41                 :            :     }
+      42                 :            : 
+      43                 :            :     function mint() external {
+      44                 :          0 :         _mint(msg.sender, 50000000);
+      45                 :            :     }
+      46                 :            : 
+      47                 :            :     function transferFrom(
+      48                 :            :         address sender,
+      49                 :            :         address recipient,
+      50                 :            :         uint256 amount
+      51                 :            :     ) public virtual override(IERC20Upgradeable, ERC20Upgradeable, ICustomToken) returns (bool) {
+      52                 :          0 :         return ERC20Upgradeable.transferFrom(sender, recipient, amount);
+      53                 :            :     }
+      54                 :            : 
+      55                 :            :     function balanceOf(address account)
+      56                 :            :         public
+      57                 :            :         view
+      58                 :            :         virtual
+      59                 :            :         override(IERC20Upgradeable, ERC20Upgradeable, ICustomToken)
+      60                 :            :         returns (uint256)
+      61                 :            :     {
+      62                 :          0 :         return ERC20Upgradeable.balanceOf(account);
+      63                 :            :     }
+      64                 :            : 
+      65                 :            :     /// @dev we only set shouldRegisterGateway to true when in `registerTokenOnL2`
+      66                 :            :     function isArbitrumEnabled() external view override returns (uint8) {
+      67         [ #  # ]:          0 :         require(shouldRegisterGateway, "NOT_EXPECTED_CALL");
+      68                 :          0 :         return uint8(0xb1);
+      69                 :            :     }
+      70                 :            : 
+      71                 :            :     function registerTokenOnL2(
+      72                 :            :         address l2CustomTokenAddress,
+      73                 :            :         uint256 maxSubmissionCostForCustomGateway,
+      74                 :            :         uint256 maxSubmissionCostForRouter,
+      75                 :            :         uint256 maxGasForCustomGateway,
+      76                 :            :         uint256 maxGasForRouter,
+      77                 :            :         uint256 gasPriceBid,
+      78                 :            :         uint256 valueForGateway,
+      79                 :            :         uint256 valueForRouter,
+      80                 :            :         address creditBackAddress
+      81                 :            :     ) public payable override {
+      82                 :            :         // we temporarily set `shouldRegisterGateway` to true for the callback in registerTokenToL2 to succeed
+      83                 :          0 :         bool prev = shouldRegisterGateway;
+      84                 :          0 :         shouldRegisterGateway = true;
+      85                 :            : 
+      86                 :          0 :         IL1CustomGateway(gateway).registerTokenToL2{ value: valueForGateway }(
+      87                 :            :             l2CustomTokenAddress,
+      88                 :            :             maxGasForCustomGateway,
+      89                 :            :             gasPriceBid,
+      90                 :            :             maxSubmissionCostForCustomGateway,
+      91                 :            :             creditBackAddress
+      92                 :            :         );
+      93                 :            : 
+      94                 :          0 :         IGatewayRouter2(router).setGateway{ value: valueForRouter }(
+      95                 :            :             gateway,
+      96                 :            :             maxGasForRouter,
+      97                 :            :             gasPriceBid,
+      98                 :            :             maxSubmissionCostForRouter,
+      99                 :            :             creditBackAddress
+     100                 :            :         );
+     101                 :            : 
+     102                 :          0 :         shouldRegisterGateway = prev;
+     103                 :            :     }
+     104                 :            : }
+     105                 :            : 
+     106                 :            : contract MintableTestCustomTokenL1 is L1MintableToken, TestCustomTokenL1 {
+     107                 :            :     constructor(address _gateway, address _router) TestCustomTokenL1(_gateway, _router) {}
+     108                 :            : 
+     109                 :            :     modifier onlyGateway() {
+     110                 :            :         require(msg.sender == gateway, "ONLY_l1GATEWAY");
+     111                 :            :         _;
+     112                 :            :     }
+     113                 :            : 
+     114                 :            :     function bridgeMint(address account, uint256 amount)
+     115                 :            :         public
+     116                 :            :         override(L1MintableToken)
+     117                 :            :         onlyGateway
+     118                 :            :     {
+     119                 :          0 :         _mint(account, amount);
+     120                 :            :     }
+     121                 :            : 
+     122                 :            :     function balanceOf(address account)
+     123                 :            :         public
+     124                 :            :         view
+     125                 :            :         virtual
+     126                 :            :         override(TestCustomTokenL1, ICustomToken)
+     127                 :            :         returns (uint256 amount)
+     128                 :            :     {
+     129                 :          0 :         return super.balanceOf(account);
+     130                 :            :     }
+     131                 :            : 
+     132                 :            :     function transferFrom(
+     133                 :            :         address sender,
+     134                 :            :         address recipient,
+     135                 :            :         uint256 amount
+     136                 :            :     ) public virtual override(TestCustomTokenL1, ICustomToken) returns (bool) {
+     137                 :          0 :         return super.transferFrom(sender, recipient, amount);
+     138                 :            :     }
+     139                 :            : }
+     140                 :            : 
+     141                 :            : contract ReverseTestCustomTokenL1 is L1ReverseToken, MintableTestCustomTokenL1 {
+     142                 :            :     constructor(address _gateway, address _router) MintableTestCustomTokenL1(_gateway, _router) {}
+     143                 :            : 
+     144                 :            :     function bridgeBurn(address account, uint256 amount)
+     145                 :            :         public
+     146                 :            :         override(L1ReverseToken)
+     147                 :            :         onlyGateway
+     148                 :            :     {
+     149                 :          0 :         _burn(account, amount);
+     150                 :            :     }
+     151                 :            : 
+     152                 :            :     function balanceOf(address account)
+     153                 :            :         public
+     154                 :            :         view
+     155                 :            :         override(MintableTestCustomTokenL1, ICustomToken)
+     156                 :            :         returns (uint256 amount)
+     157                 :            :     {
+     158                 :          0 :         return super.balanceOf(account);
+     159                 :            :     }
+     160                 :            : 
+     161                 :            :     function transferFrom(
+     162                 :            :         address sender,
+     163                 :            :         address recipient,
+     164                 :            :         uint256 amount
+     165                 :            :     ) public override(MintableTestCustomTokenL1, ICustomToken) returns (bool) {
+     166                 :          0 :         return super.transferFrom(sender, recipient, amount);
+     167                 :            :     }
+     168                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestERC20.sol.func-sort-c.html b/coverage/test/TestERC20.sol.func-sort-c.html new file mode 100644 index 0000000000..c2a02ea51f --- /dev/null +++ b/coverage/test/TestERC20.sol.func-sort-c.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - test/TestERC20.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11010.0 %
Date:2023-04-27 16:26:32Functions:1520.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
Bytes32ERC20.approve0
Bytes32ERC20.mint0
Bytes32ERC20.transfer0
Bytes32ERC20.transferFrom0
TestERC20.mint2
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestERC20.sol.func.html b/coverage/test/TestERC20.sol.func.html new file mode 100644 index 0000000000..9c358efc02 --- /dev/null +++ b/coverage/test/TestERC20.sol.func.html @@ -0,0 +1,101 @@ + + + + + + + LCOV - lcov.info - test/TestERC20.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11010.0 %
Date:2023-04-27 16:26:32Functions:1520.0 %
Branches:020.0 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
Bytes32ERC20.approve0
Bytes32ERC20.mint0
Bytes32ERC20.transfer0
Bytes32ERC20.transferFrom0
TestERC20.mint2
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestERC20.sol.gcov.html b/coverage/test/TestERC20.sol.gcov.html new file mode 100644 index 0000000000..be999026db --- /dev/null +++ b/coverage/test/TestERC20.sol.gcov.html @@ -0,0 +1,160 @@ + + + + + + + LCOV - lcov.info - test/TestERC20.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11010.0 %
Date:2023-04-27 16:26:32Functions:1520.0 %
Branches:020.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../libraries/aeERC20.sol";
+      22                 :            : 
+      23                 :            : contract TestERC20 is aeERC20 {
+      24                 :            :     constructor() {
+      25                 :            :         aeERC20._initialize("IntArbTestToken", "IARB", uint8(18));
+      26                 :            :     }
+      27                 :            : 
+      28                 :            :     function mint() external {
+      29                 :          2 :         _mint(msg.sender, 50000000);
+      30                 :            :     }
+      31                 :            : }
+      32                 :            : 
+      33                 :            : // test token code inspired from maker
+      34                 :            : contract Bytes32ERC20 {
+      35                 :            :     mapping(address => uint256) public balanceOf;
+      36                 :            :     mapping(address => mapping(address => uint256)) public allowance;
+      37                 :            : 
+      38                 :            :     function transfer(address dst, uint256 wad) public returns (bool) {
+      39                 :          0 :         return transferFrom(msg.sender, dst, wad);
+      40                 :            :     }
+      41                 :            : 
+      42                 :            :     function transferFrom(
+      43                 :            :         address src,
+      44                 :            :         address dst,
+      45                 :            :         uint256 wad
+      46                 :            :     ) public returns (bool) {
+      47         [ #  # ]:          0 :         if (src != msg.sender) {
+      48                 :          0 :             allowance[src][msg.sender] = allowance[src][msg.sender] - wad;
+      49                 :            :         }
+      50                 :            : 
+      51                 :          0 :         balanceOf[src] = balanceOf[src] - wad;
+      52                 :          0 :         balanceOf[dst] = balanceOf[dst] + wad;
+      53                 :            : 
+      54                 :          0 :         return true;
+      55                 :            :     }
+      56                 :            : 
+      57                 :            :     function approve(address guy, uint256 wad) public returns (bool) {
+      58                 :          0 :         allowance[msg.sender][guy] = wad;
+      59                 :          0 :         return true;
+      60                 :            :     }
+      61                 :            : 
+      62                 :            :     function mint() public {
+      63                 :          0 :         balanceOf[msg.sender] += 1 ether;
+      64                 :            :     }
+      65                 :            : }
+      66                 :            : 
+      67                 :            : contract Bytes32ERC20WithMetadata is Bytes32ERC20 {
+      68                 :            :     bytes32 public name = 0x4d616b6572000000000000000000000000000000000000000000000000000000;
+      69                 :            :     bytes32 public symbol = 0x4d4b520000000000000000000000000000000000000000000000000000000000;
+      70                 :            :     // TODO: what if this overflows?
+      71                 :            :     uint8 public decimals = 18;
+      72                 :            : 
+      73                 :            :     // no totalSupply field
+      74                 :            :     // uint256 public totalSupply;
+      75                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestPostDepositCall.sol.func-sort-c.html b/coverage/test/TestPostDepositCall.sol.func-sort-c.html new file mode 100644 index 0000000000..0b8fd17d50 --- /dev/null +++ b/coverage/test/TestPostDepositCall.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - test/TestPostDepositCall.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestPostDepositCall.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:090.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2Called.onTokenTransfer0
L2Called.postDepositHook0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestPostDepositCall.sol.func.html b/coverage/test/TestPostDepositCall.sol.func.html new file mode 100644 index 0000000000..f9299f15e3 --- /dev/null +++ b/coverage/test/TestPostDepositCall.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - test/TestPostDepositCall.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestPostDepositCall.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:090.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:060.0 %
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
L2Called.onTokenTransfer0
L2Called.postDepositHook0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestPostDepositCall.sol.gcov.html b/coverage/test/TestPostDepositCall.sol.gcov.html new file mode 100644 index 0000000000..470ee77907 --- /dev/null +++ b/coverage/test/TestPostDepositCall.sol.gcov.html @@ -0,0 +1,136 @@ + + + + + + + LCOV - lcov.info - test/TestPostDepositCall.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestPostDepositCall.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:090.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:060.0 %
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : /*
+       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
+       5                 :            :  *
+       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
+       7                 :            :  * you may not use this file except in compliance with the License.
+       8                 :            :  * You may obtain a copy of the License at
+       9                 :            :  *
+      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
+      11                 :            :  *
+      12                 :            :  * Unless required by applicable law or agreed to in writing, software
+      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
+      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      15                 :            :  * See the License for the specific language governing permissions and
+      16                 :            :  * limitations under the License.
+      17                 :            :  */
+      18                 :            : 
+      19                 :            : pragma solidity ^0.8.0;
+      20                 :            : 
+      21                 :            : import "../libraries/ITransferAndCall.sol";
+      22                 :            : 
+      23                 :            : contract L2Called is ITransferAndCallReceiver {
+      24                 :            :     event Called(uint256 num);
+      25                 :            : 
+      26                 :            :     constructor() {}
+      27                 :            : 
+      28                 :            :     // This function can be anything
+      29                 :            :     function postDepositHook(uint256 num) public {
+      30                 :          0 :         emit Called(num);
+      31                 :            :     }
+      32                 :            : 
+      33                 :            :     function onTokenTransfer(
+      34                 :            :         address, /* sender */
+      35                 :            :         uint256, /* amount */
+      36                 :            :         bytes calldata data
+      37                 :            :     ) external override {
+      38                 :          0 :         uint256 num = abi.decode(data, (uint256));
+      39                 :            : 
+      40         [ #  # ]:          0 :         if (num == 5) {
+      41                 :          0 :             postDepositHook(num);
+      42         [ #  # ]:          0 :         } else if (num == 7) {
+      43                 :          0 :             revert("should fail because 7");
+      44         [ #  # ]:          0 :         } else if (num == 9) {
+      45                 :            :             // this should use all gas
+      46                 :          0 :             while (gasleft() > 0) {}
+      47                 :            :         } else {
+      48                 :          0 :             revert("should fail");
+      49                 :            :         }
+      50                 :            :     }
+      51                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestWETH9.sol.func-sort-c.html b/coverage/test/TestWETH9.sol.func-sort-c.html new file mode 100644 index 0000000000..6b96b51dd5 --- /dev/null +++ b/coverage/test/TestWETH9.sol.func-sort-c.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - test/TestWETH9.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestWETH9.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TestWETH9.deposit0
TestWETH9.withdraw0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestWETH9.sol.func.html b/coverage/test/TestWETH9.sol.func.html new file mode 100644 index 0000000000..e69ff31d57 --- /dev/null +++ b/coverage/test/TestWETH9.sol.func.html @@ -0,0 +1,89 @@ + + + + + + + LCOV - lcov.info - test/TestWETH9.sol - functions + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestWETH9.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ +
+ + + + + + + + + + + + + + +

Function Name Sort by function nameHit count Sort by hit count
TestWETH9.deposit0
TestWETH9.withdraw0
+
+
+ + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/TestWETH9.sol.gcov.html b/coverage/test/TestWETH9.sol.gcov.html new file mode 100644 index 0000000000..7d0a0015f5 --- /dev/null +++ b/coverage/test/TestWETH9.sol.gcov.html @@ -0,0 +1,105 @@ + + + + + + + LCOV - lcov.info - test/TestWETH9.sol + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - test - TestWETH9.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
+
+ + + + + + + + +

+
           Branch data     Line data    Source code
+
+       1                 :            : // SPDX-License-Identifier: Apache-2.0
+       2                 :            : 
+       3                 :            : pragma solidity ^0.8.0;
+       4                 :            : 
+       5                 :            : import "../libraries/IWETH9.sol";
+       6                 :            : import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
+       7                 :            : import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
+       8                 :            : 
+       9                 :            : contract TestWETH9 is ERC20, IWETH9 {
+      10                 :            :     constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {}
+      11                 :            : 
+      12                 :            :     function deposit() external payable override {
+      13                 :          0 :         _mint(msg.sender, msg.value);
+      14                 :            :     }
+      15                 :            : 
+      16                 :            :     function withdraw(uint256 _amount) external override {
+      17                 :          0 :         _burn(msg.sender, _amount);
+      18                 :          0 :         payable(address(msg.sender)).transfer(_amount);
+      19                 :            :     }
+      20                 :            : }
+
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/index-sort-b.html b/coverage/test/index-sort-b.html new file mode 100644 index 0000000000..c61bc0e5cd --- /dev/null +++ b/coverage/test/index-sort-b.html @@ -0,0 +1,215 @@ + + + + + + + LCOV - lcov.info - test + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - testHitTotalCoverage
Test:lcov.infoLines:156722.4 %
Date:2023-04-27 16:26:32Functions:73718.9 %
Branches:21414.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
TestERC20.sol +
10.0%10.0%
+
10.0 %1 / 1020.0 %1 / 50.0 %0 / 2
TestCustomTokenL1.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 110.0 %0 / 2
TestPostDepositCall.sol +
0.0%
+
0.0 %0 / 90.0 %0 / 20.0 %0 / 6
InboxMock.sol +
87.5%87.5%
+
87.5 %14 / 16100.0 %6 / 650.0 %2 / 4
TestArbCustomTokenBurnFee.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 1-0 / 0
TestWETH9.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 2-0 / 0
TestArbCustomToken.sol +
0.0%
+
0.0 %0 / 40.0 %0 / 6-0 / 0
ArbSysMock.sol +
0.0%
+
0.0 %0 / 40.0 %0 / 1-0 / 0
AddressMappingTest.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
TestBytesParser.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/index-sort-f.html b/coverage/test/index-sort-f.html new file mode 100644 index 0000000000..478c48474b --- /dev/null +++ b/coverage/test/index-sort-f.html @@ -0,0 +1,215 @@ + + + + + + + LCOV - lcov.info - test + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - testHitTotalCoverage
Test:lcov.infoLines:156722.4 %
Date:2023-04-27 16:26:32Functions:73718.9 %
Branches:21414.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
TestArbCustomTokenBurnFee.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 1-0 / 0
ArbSysMock.sol +
0.0%
+
0.0 %0 / 40.0 %0 / 1-0 / 0
AddressMappingTest.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
TestWETH9.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 2-0 / 0
TestPostDepositCall.sol +
0.0%
+
0.0 %0 / 90.0 %0 / 20.0 %0 / 6
TestBytesParser.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
TestArbCustomToken.sol +
0.0%
+
0.0 %0 / 40.0 %0 / 6-0 / 0
TestCustomTokenL1.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 110.0 %0 / 2
TestERC20.sol +
10.0%10.0%
+
10.0 %1 / 1020.0 %1 / 50.0 %0 / 2
InboxMock.sol +
87.5%87.5%
+
87.5 %14 / 16100.0 %6 / 650.0 %2 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/index-sort-l.html b/coverage/test/index-sort-l.html new file mode 100644 index 0000000000..def397516c --- /dev/null +++ b/coverage/test/index-sort-l.html @@ -0,0 +1,215 @@ + + + + + + + LCOV - lcov.info - test + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - testHitTotalCoverage
Test:lcov.infoLines:156722.4 %
Date:2023-04-27 16:26:32Functions:73718.9 %
Branches:21414.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
AddressMappingTest.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
TestArbCustomTokenBurnFee.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 1-0 / 0
TestBytesParser.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
TestWETH9.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 2-0 / 0
TestArbCustomToken.sol +
0.0%
+
0.0 %0 / 40.0 %0 / 6-0 / 0
ArbSysMock.sol +
0.0%
+
0.0 %0 / 40.0 %0 / 1-0 / 0
TestPostDepositCall.sol +
0.0%
+
0.0 %0 / 90.0 %0 / 20.0 %0 / 6
TestCustomTokenL1.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 110.0 %0 / 2
TestERC20.sol +
10.0%10.0%
+
10.0 %1 / 1020.0 %1 / 50.0 %0 / 2
InboxMock.sol +
87.5%87.5%
+
87.5 %14 / 16100.0 %6 / 650.0 %2 / 4
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/test/index.html b/coverage/test/index.html new file mode 100644 index 0000000000..b85fff851c --- /dev/null +++ b/coverage/test/index.html @@ -0,0 +1,215 @@ + + + + + + + LCOV - lcov.info - test + + + + + + + + + + + + + + +
LCOV - code coverage report
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Current view:top level - testHitTotalCoverage
Test:lcov.infoLines:156722.4 %
Date:2023-04-27 16:26:32Functions:73718.9 %
Branches:21414.3 %
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
AddressMappingTest.sol +
0.0%
+
0.0 %0 / 10.0 %0 / 1-0 / 0
ArbSysMock.sol +
0.0%
+
0.0 %0 / 40.0 %0 / 1-0 / 0
InboxMock.sol +
87.5%87.5%
+
87.5 %14 / 16100.0 %6 / 650.0 %2 / 4
TestArbCustomToken.sol +
0.0%
+
0.0 %0 / 40.0 %0 / 6-0 / 0
TestArbCustomTokenBurnFee.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 1-0 / 0
TestBytesParser.sol +
0.0%
+
0.0 %0 / 20.0 %0 / 2-0 / 0
TestCustomTokenL1.sol +
0.0%
+
0.0 %0 / 160.0 %0 / 110.0 %0 / 2
TestERC20.sol +
10.0%10.0%
+
10.0 %1 / 1020.0 %1 / 50.0 %0 / 2
TestPostDepositCall.sol +
0.0%
+
0.0 %0 / 90.0 %0 / 20.0 %0 / 6
TestWETH9.sol +
0.0%
+
0.0 %0 / 30.0 %0 / 2-0 / 0
+
+
+ + + + +
Generated by: LCOV version 1.16
+
+ + + diff --git a/coverage/updown.png b/coverage/updown.png new file mode 100644 index 0000000000000000000000000000000000000000..aa56a238b3e6c435265250f9266cd1b8caba0f20 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^AT}Qd8;}%R+`Ae`*?77*hG?8mPH5^{)z4*}Q$iB}huR`+ literal 0 HcmV?d00001 diff --git a/lcov.info b/lcov.info new file mode 100644 index 0000000000..acfc368967 --- /dev/null +++ b/lcov.info @@ -0,0 +1,1786 @@ +TN: +SF:contracts/rpc-utils/MulticallV2.sol +FN:141,ArbMulticall2.aggregate +FNDA:0,ArbMulticall2.aggregate +DA:145,0 +DA:146,0 +DA:147,0 +DA:148,0 +DA:149,0 +BRDA:149,0,0,- +BRDA:149,0,1,- +DA:150,0 +FN:154,ArbMulticall2.blockAndAggregate +FNDA:0,ArbMulticall2.blockAndAggregate +DA:162,0 +FN:165,ArbMulticall2.getBlockHash +FNDA:0,ArbMulticall2.getBlockHash +DA:166,0 +FN:169,ArbMulticall2.getBlockNumber +FNDA:0,ArbMulticall2.getBlockNumber +DA:170,0 +FN:173,ArbMulticall2.getL1BlockNumber +FNDA:0,ArbMulticall2.getL1BlockNumber +DA:174,0 +FN:177,ArbMulticall2.getCurrentBlockCoinbase +FNDA:0,ArbMulticall2.getCurrentBlockCoinbase +DA:178,0 +FN:181,ArbMulticall2.getCurrentBlockDifficulty +FNDA:0,ArbMulticall2.getCurrentBlockDifficulty +DA:182,0 +FN:185,ArbMulticall2.getCurrentBlockGasLimit +FNDA:0,ArbMulticall2.getCurrentBlockGasLimit +DA:186,0 +FN:189,ArbMulticall2.getCurrentBlockTimestamp +FNDA:0,ArbMulticall2.getCurrentBlockTimestamp +DA:190,0 +FN:193,ArbMulticall2.getEthBalance +FNDA:0,ArbMulticall2.getEthBalance +DA:194,0 +FN:197,ArbMulticall2.getLastBlockHash +FNDA:0,ArbMulticall2.getLastBlockHash +DA:198,0 +FN:201,ArbMulticall2.tryAggregateGasRation +FNDA:0,ArbMulticall2.tryAggregateGasRation +DA:205,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:212,0 +BRDA:212,1,0,- +BRDA:212,1,1,- +DA:213,0 +BRDA:213,2,0,- +BRDA:213,2,1,- +DA:216,0 +FN:220,ArbMulticall2.tryAggregate +FNDA:0,ArbMulticall2.tryAggregate +DA:224,0 +DA:225,0 +DA:226,0 +DA:228,0 +BRDA:228,3,0,- +BRDA:228,3,1,- +DA:229,0 +BRDA:229,4,0,- +BRDA:229,4,1,- +DA:232,0 +FN:236,ArbMulticall2.tryBlockAndAggregate +FNDA:0,ArbMulticall2.tryBlockAndAggregate +DA:244,0 +DA:245,0 +DA:246,0 +FN:25,Multicall2.aggregate +FNDA:0,Multicall2.aggregate +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +BRDA:33,0,0,- +BRDA:33,0,1,- +DA:34,0 +FN:38,Multicall2.blockAndAggregate +FNDA:0,Multicall2.blockAndAggregate +DA:46,0 +FN:49,Multicall2.getBlockHash +FNDA:0,Multicall2.getBlockHash +DA:50,0 +FN:53,Multicall2.getBlockNumber +FNDA:0,Multicall2.getBlockNumber +DA:54,0 +FN:57,Multicall2.getCurrentBlockCoinbase +FNDA:0,Multicall2.getCurrentBlockCoinbase +DA:58,0 +FN:61,Multicall2.getCurrentBlockDifficulty +FNDA:0,Multicall2.getCurrentBlockDifficulty +DA:62,0 +FN:65,Multicall2.getCurrentBlockGasLimit +FNDA:0,Multicall2.getCurrentBlockGasLimit +DA:66,0 +FN:69,Multicall2.getCurrentBlockTimestamp +FNDA:0,Multicall2.getCurrentBlockTimestamp +DA:70,0 +FN:73,Multicall2.getEthBalance +FNDA:0,Multicall2.getEthBalance +DA:74,0 +FN:77,Multicall2.getLastBlockHash +FNDA:0,Multicall2.getLastBlockHash +DA:78,0 +FN:81,Multicall2.tryAggregateGasRation +FNDA:0,Multicall2.tryAggregateGasRation +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:92,0 +BRDA:92,1,0,- +BRDA:92,1,1,- +DA:93,0 +BRDA:93,2,0,- +BRDA:93,2,1,- +DA:96,0 +FN:100,Multicall2.tryAggregate +FNDA:0,Multicall2.tryAggregate +DA:104,0 +DA:105,0 +DA:106,0 +DA:108,0 +BRDA:108,3,0,- +BRDA:108,3,1,- +DA:109,0 +BRDA:109,4,0,- +BRDA:109,4,1,- +DA:112,0 +FN:116,Multicall2.tryBlockAndAggregate +FNDA:0,Multicall2.tryBlockAndAggregate +DA:124,0 +DA:125,0 +DA:126,0 +FNF:27 +FNH:0 +LF:63 +LH:0 +BRF:20 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol +FN:30,L2ArbitrumMessenger.sendTxToL1 +FNDA:0,L2ArbitrumMessenger.sendTxToL1 +DA:36,0 +DA:37,0 +DA:38,0 +FNF:1 +FNH:0 +LF:3 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/arbitrum/ReverseArbToken.sol +FN:33,ReverseArbToken.bridgeMint +FNDA:0,ReverseArbToken.bridgeMint +DA:34,0 +FN:37,ReverseArbToken.bridgeBurn +FNDA:0,ReverseArbToken.bridgeBurn +DA:38,0 +FNF:2 +FNH:0 +LF:2 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/arbitrum/StandardArbERC20.sol +FN:43,StandardArbERC20.bridgeInit +FNDA:0,StandardArbERC20.bridgeInit +DA:44,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:63,0 +DA:74,0 +FN:81,StandardArbERC20.decimals +FNDA:0,StandardArbERC20.decimals +DA:83,0 +BRDA:83,0,0,- +BRDA:83,0,1,- +DA:84,0 +FN:87,StandardArbERC20.name +FNDA:0,StandardArbERC20.name +DA:89,0 +BRDA:89,1,0,- +BRDA:89,1,1,- +DA:90,0 +FN:93,StandardArbERC20.symbol +FNDA:0,StandardArbERC20.symbol +DA:95,0 +BRDA:95,2,0,- +BRDA:95,2,1,- +DA:96,0 +FNF:4 +FNH:0 +LF:12 +LH:0 +BRF:6 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol +FN:64,L2ArbitrumGateway.postUpgradeInit +FNDA:0,L2ArbitrumGateway.postUpgradeInit +DA:67,0 +DA:68,0 +BRDA:68,0,0,- +BRDA:68,0,1,- +FN:72,L2ArbitrumGateway._initialize +FNDA:0,L2ArbitrumGateway._initialize +DA:73,0 +DA:75,0 +BRDA:75,1,0,- +BRDA:75,1,1,- +FN:78,L2ArbitrumGateway.createOutboundTx +FNDA:0,L2ArbitrumGateway.createOutboundTx +DA:87,0 +DA:88,0 +FN:98,L2ArbitrumGateway.getOutboundCalldata +FNDA:0,L2ArbitrumGateway.getOutboundCalldata +DA:105,0 +DA:114,0 +FN:117,L2ArbitrumGateway.outboundTransfer +FNDA:0,L2ArbitrumGateway.outboundTransfer +DA:123,0 +FN:133,L2ArbitrumGateway.outboundTransfer +FNDA:0,L2ArbitrumGateway.outboundTransfer +DA:147,0 +BRDA:147,2,0,- +BRDA:147,2,1,- +DA:149,0 +DA:150,0 +DA:152,0 +BRDA:152,3,0,- +BRDA:152,3,1,- +DA:153,0 +DA:155,0 +DA:156,0 +DA:160,0 +BRDA:160,4,0,- +BRDA:160,4,1,- +DA:162,0 +DA:164,0 +DA:165,0 +BRDA:165,5,0,- +BRDA:165,5,1,- +DA:166,0 +BRDA:166,6,0,- +BRDA:166,6,1,- +DA:168,0 +DA:169,0 +DA:171,0 +FN:174,L2ArbitrumGateway.triggerWithdrawal +FNDA:0,L2ArbitrumGateway.triggerWithdrawal +DA:182,0 +DA:184,0 +DA:189,0 +DA:190,0 +FN:193,L2ArbitrumGateway.outboundEscrowTransfer +FNDA:0,L2ArbitrumGateway.outboundEscrowTransfer +DA:201,0 +DA:204,0 +FN:207,L2ArbitrumGateway.inboundEscrowTransfer +FNDA:0,L2ArbitrumGateway.inboundEscrowTransfer +DA:213,0 +FN:227,L2ArbitrumGateway.finalizeInboundTransfer +FNDA:0,L2ArbitrumGateway.finalizeInboundTransfer +DA:234,0 +DA:237,0 +BRDA:237,7,0,- +BRDA:237,7,1,- +DA:239,0 +DA:242,0 +DA:244,0 +BRDA:244,8,0,- +BRDA:244,8,1,- +DA:245,0 +DA:253,0 +BRDA:253,9,0,- +BRDA:253,9,1,- +DA:259,0 +DA:263,0 +DA:264,0 +BRDA:264,10,0,- +BRDA:264,10,1,- +DA:265,0 +DA:270,0 +DA:271,0 +BRDA:271,11,0,- +BRDA:271,11,1,- +DA:272,0 +DA:276,0 +BRDA:276,12,0,- +BRDA:276,12,1,- +DA:279,0 +DA:280,0 +DA:284,0 +DA:285,0 +DA:287,0 +FNF:10 +FNH:0 +LF:51 +LH:0 +BRF:26 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol +FN:29,L2CustomGateway.initialize +FNDA:0,L2CustomGateway.initialize +DA:30,0 +FN:36,L2CustomGateway.handleNoContract +FNDA:0,L2CustomGateway.handleNoContract +DA:48,0 +DA:49,0 +FN:59,L2CustomGateway.calculateL2TokenAddress +FNDA:0,L2CustomGateway.calculateL2TokenAddress +DA:60,0 +FN:63,L2CustomGateway.registerTokenFromL1 +FNDA:0,L2CustomGateway.registerTokenFromL1 +DA:68,0 +DA:71,0 +DA:72,0 +FNF:4 +FNH:0 +LF:7 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol +FN:30,L2ERC20Gateway.initialize +FNDA:0,L2ERC20Gateway.initialize +DA:35,0 +DA:36,0 +BRDA:36,0,0,- +BRDA:36,0,1,- +DA:37,0 +FN:47,L2ERC20Gateway.calculateL2TokenAddress +FNDA:0,L2ERC20Gateway.calculateL2TokenAddress +DA:55,0 +FN:62,L2ERC20Gateway.cloneableProxyHash +FNDA:0,L2ERC20Gateway.cloneableProxyHash +DA:63,0 +FN:66,L2ERC20Gateway.getUserSalt +FNDA:0,L2ERC20Gateway.getUserSalt +DA:67,0 +FN:78,L2ERC20Gateway.handleNoContract +FNDA:0,L2ERC20Gateway.handleNoContract +DA:86,0 +DA:87,0 +DA:89,0 +DA:91,0 +BRDA:91,1,0,- +BRDA:91,1,1,- +DA:92,0 +DA:97,0 +DA:98,0 +FNF:5 +FNH:0 +LF:13 +LH:0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol +FN:39,L2GatewayRouter.initialize +FNDA:0,L2GatewayRouter.initialize +DA:40,0 +FN:43,L2GatewayRouter.setGateway +FNDA:0,L2GatewayRouter.setGateway +DA:48,0 +BRDA:48,0,0,- +BRDA:48,0,1,- +DA:50,0 +DA:51,0 +DA:52,0 +FN:56,L2GatewayRouter.outboundTransfer +FNDA:0,L2GatewayRouter.outboundTransfer +DA:62,0 +FN:65,L2GatewayRouter.setDefaultGateway +FNDA:0,L2GatewayRouter.setDefaultGateway +DA:66,0 +DA:67,0 +FNF:4 +FNH:0 +LF:8 +LH:0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol +FN:39,L2ReverseCustomGateway.inboundEscrowTransfer +FNDA:0,L2ReverseCustomGateway.inboundEscrowTransfer +DA:44,0 +FN:47,L2ReverseCustomGateway.outboundEscrowTransfer +FNDA:0,L2ReverseCustomGateway.outboundEscrowTransfer +DA:52,0 +DA:57,0 +DA:58,0 +DA:59,0 +FNF:2 +FNH:0 +LF:5 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol +FN:32,L2WethGateway.initialize +FNDA:0,L2WethGateway.initialize +DA:38,0 +DA:39,0 +BRDA:39,0,0,- +BRDA:39,0,1,- +DA:40,0 +BRDA:40,1,0,- +BRDA:40,1,1,- +DA:41,0 +DA:42,0 +FN:49,L2WethGateway.handleNoContract +FNDA:0,L2WethGateway.handleNoContract +DA:61,0 +DA:62,0 +FN:72,L2WethGateway.calculateL2TokenAddress +FNDA:0,L2WethGateway.calculateL2TokenAddress +DA:73,0 +BRDA:73,2,0,- +BRDA:73,2,1,- +DA:75,0 +DA:77,0 +FN:80,L2WethGateway.inboundEscrowTransfer +FNDA:0,L2WethGateway.inboundEscrowTransfer +DA:85,0 +DA:86,0 +FN:89,L2WethGateway.createOutboundTx +FNDA:0,L2WethGateway.createOutboundTx +DA:95,0 +DA:96,0 +FNF:5 +FNH:0 +LF:14 +LH:0 +BRF:6 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol +FN:35,L1ArbitrumMessenger.sendTxToL2CustomRefund +FNDA:4,L1ArbitrumMessenger.sendTxToL2CustomRefund +DA:46,4 +FN:61,L1ArbitrumMessenger.sendTxToL2 +FNDA:7,L1ArbitrumMessenger.sendTxToL2 +DA:71,7 +FN:85,L1ArbitrumMessenger.sendTxToL2CustomRefund +FNDA:17,L1ArbitrumMessenger.sendTxToL2CustomRefund +DA:97,17 +DA:109,17 +DA:110,17 +FN:113,L1ArbitrumMessenger.sendTxToL2 +FNDA:13,L1ArbitrumMessenger.sendTxToL2 +DA:124,13 +FN:139,L1ArbitrumMessenger.getBridge +FNDA:10,L1ArbitrumMessenger.getBridge +DA:140,10 +FN:144,L1ArbitrumMessenger.getL2ToL1Sender +FNDA:4,L1ArbitrumMessenger.getL2ToL1Sender +DA:145,4 +DA:146,4 +DA:148,4 +BRDA:148,0,0,- +BRDA:148,0,1,4 +DA:149,4 +FN:166,L1ArbitrumMessenger._createRetryable +FNDA:15,L1ArbitrumMessenger._createRetryable +DA:178,15 +FNF:7 +FNH:7 +LF:12 +LH:12 +BRF:2 +BRH:1 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol +FN:62,L1ArbitrumExtendedGateway.transferExitAndCall +FNDA:5636,L1ArbitrumExtendedGateway.transferExitAndCall +DA:71,5636 +DA:74,5636 +BRDA:74,0,0,2 +BRDA:74,0,1,5634 +DA:76,5634 +BRDA:76,1,0,2 +BRDA:76,1,1,5632 +DA:78,5632 +DA:80,5632 +BRDA:80,2,0,1024 +BRDA:80,2,1,2048 +DA:81,3584 +BRDA:81,3,0,512 +BRDA:81,3,1,3072 +DA:82,3072 +DA:87,3072 +BRDA:87,4,0,1024 +BRDA:87,4,1,2048 +DA:90,4096 +FN:101,L1ArbitrumExtendedGateway.getExternalCall +FNDA:1024,L1ArbitrumExtendedGateway.getExternalCall +DA:107,6662 +DA:108,6662 +DA:113,6662 +BRDA:113,5,0,- +BRDA:113,5,1,- +DA:114,2048 +DA:116,4614 +FN:120,L1ArbitrumExtendedGateway.setRedirectedExit +FNDA:5632,L1ArbitrumExtendedGateway.setRedirectedExit +DA:126,5632 +DA:127,5632 +FN:130,L1ArbitrumExtendedGateway.encodeWithdrawal +FNDA:512,L1ArbitrumExtendedGateway.encodeWithdrawal +DA:136,12806 +FNF:4 +FNH:4 +LF:17 +LH:17 +BRF:12 +BRH:10 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol +FN:76,L1ArbitrumGateway.postUpgradeInit +FNDA:2,L1ArbitrumGateway.postUpgradeInit +DA:79,2 +DA:80,2 +BRDA:80,0,0,2 +BRDA:80,0,1,- +FN:84,L1ArbitrumGateway._initialize +FNDA:13,L1ArbitrumGateway._initialize +DA:89,13 +DA:91,13 +BRDA:91,1,0,- +BRDA:91,1,1,13 +DA:92,13 +BRDA:92,2,0,- +BRDA:92,2,1,13 +DA:93,13 +FN:104,L1ArbitrumGateway.finalizeInboundTransfer +FNDA:6,L1ArbitrumGateway.finalizeInboundTransfer +DA:112,2 +DA:116,2 +BRDA:116,3,0,- +BRDA:116,3,1,2 +DA:118,0 +DA:122,2 +DA:123,2 +DA:125,2 +FN:128,L1ArbitrumGateway.getExternalCall +FNDA:0,L1ArbitrumGateway.getExternalCall +DA:135,0 +DA:136,0 +FN:139,L1ArbitrumGateway.inboundEscrowTransfer +FNDA:2,L1ArbitrumGateway.inboundEscrowTransfer +DA:145,2 +FN:151,L1ArbitrumGateway.createOutboundTxCustomRefund +FNDA:2,L1ArbitrumGateway.createOutboundTxCustomRefund +DA:165,2 +FN:185,L1ArbitrumGateway.createOutboundTx +FNDA:0,L1ArbitrumGateway.createOutboundTx +DA:193,0 +FN:208,L1ArbitrumGateway.outboundTransfer +FNDA:2,L1ArbitrumGateway.outboundTransfer +DA:216,2 +FN:238,L1ArbitrumGateway.outboundTransferCustomRefund +FNDA:12,L1ArbitrumGateway.outboundTransferCustomRefund +DA:247,12 +BRDA:247,4,0,2 +BRDA:247,4,1,10 +DA:250,10 +DA:251,10 +DA:252,10 +DA:254,10 +DA:255,10 +DA:256,10 +BRDA:256,5,0,10 +BRDA:256,5,1,- +DA:258,10 +DA:260,0 +DA:261,0 +DA:264,10 +DA:267,10 +BRDA:267,6,0,2 +BRDA:267,6,1,8 +DA:269,8 +BRDA:269,7,0,2 +BRDA:269,7,1,6 +DA:270,6 +DA:271,6 +BRDA:271,8,0,- +BRDA:271,8,1,6 +DA:273,6 +DA:276,4 +DA:278,4 +DA:289,4 +DA:290,4 +FN:293,L1ArbitrumGateway.outboundEscrowTransfer +FNDA:6,L1ArbitrumGateway.outboundEscrowTransfer +DA:300,6 +DA:301,6 +DA:302,4 +DA:303,4 +FN:306,L1ArbitrumGateway.getOutboundCalldata +FNDA:0,L1ArbitrumGateway.getOutboundCalldata +DA:317,0 +DA:319,0 +DA:328,0 +FN:331,L1ArbitrumGateway.supportsInterface +FNDA:512,L1ArbitrumGateway.supportsInterface +DA:340,512 +FN:359,L1ArbitrumGateway._parseUserEncodedData +FNDA:5,L1ArbitrumGateway._parseUserEncodedData +DA:367,5 +FN:382,L1ArbitrumGateway._initiateDeposit +FNDA:2,L1ArbitrumGateway._initiateDeposit +DA:392,2 +FNF:14 +FNH:11 +LF:48 +LH:39 +BRF:18 +BRH:12 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol +FN:63,L1CustomGateway.outboundTransferCustomRefund +FNDA:0,L1CustomGateway.outboundTransferCustomRefund +DA:72,0 +FN:84,L1CustomGateway.finalizeInboundTransfer +FNDA:0,L1CustomGateway.finalizeInboundTransfer +DA:92,0 +FN:95,L1CustomGateway.initialize +FNDA:6,L1CustomGateway.initialize +DA:101,6 +DA:102,6 +DA:104,6 +DA:106,6 +FN:116,L1CustomGateway.calculateL2TokenAddress +FNDA:7,L1CustomGateway.calculateL2TokenAddress +DA:117,7 +FN:128,L1CustomGateway.registerTokenToL2 +FNDA:0,L1CustomGateway.registerTokenToL2 +DA:134,0 +FN:146,L1CustomGateway.registerTokenToL2 +FNDA:6,L1CustomGateway.registerTokenToL2 +DA:153,6 +BRDA:153,0,0,- +BRDA:153,0,1,6 +DA:158,6 +DA:159,6 +BRDA:159,1,0,- +BRDA:159,1,1,- +DA:161,0 +BRDA:161,2,0,- +BRDA:161,2,1,- +DA:164,6 +DA:166,6 +DA:167,6 +DA:168,6 +DA:169,6 +DA:171,6 +DA:173,6 +DA:179,6 +FN:193,L1CustomGateway.setOwner +FNDA:0,L1CustomGateway.setOwner +DA:194,0 +BRDA:194,3,0,- +BRDA:194,3,1,- +DA:195,0 +FN:208,L1CustomGateway.forceRegisterTokenToL2 +FNDA:0,L1CustomGateway.forceRegisterTokenToL2 +DA:215,0 +BRDA:215,4,0,- +BRDA:215,4,1,- +DA:217,0 +DA:220,0 +DA:221,0 +DA:224,0 +DA:230,0 +FNF:8 +FNH:3 +LF:28 +LH:16 +BRF:10 +BRH:1 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol +FN:57,L1ERC20Gateway.outboundTransferCustomRefund +FNDA:10,L1ERC20Gateway.outboundTransferCustomRefund +DA:66,12 +FN:78,L1ERC20Gateway.finalizeInboundTransfer +FNDA:6,L1ERC20Gateway.finalizeInboundTransfer +DA:86,6 +FN:89,L1ERC20Gateway.initialize +FNDA:7,L1ERC20Gateway.initialize +DA:96,7 +DA:97,7 +BRDA:97,0,0,2 +BRDA:97,0,1,5 +DA:98,5 +BRDA:98,1,0,2 +BRDA:98,1,1,3 +DA:99,3 +DA:100,3 +DA:102,3 +DA:104,3 +FN:113,L1ERC20Gateway.callStatic +FNDA:30,L1ERC20Gateway.callStatic +DA:118,30 +DA:122,30 +DA:123,30 +FN:126,L1ERC20Gateway.getOutboundCalldata +FNDA:6,L1ERC20Gateway.getOutboundCalldata +DA:134,10 +DA:140,10 +DA:149,10 +FN:152,L1ERC20Gateway.calculateL2TokenAddress +FNDA:512,L1ERC20Gateway.calculateL2TokenAddress +DA:153,518 +DA:154,518 +FN:157,L1ERC20Gateway.getSalt +FNDA:518,L1ERC20Gateway.getSalt +DA:159,518 +FNF:7 +FNH:7 +LF:18 +LH:18 +BRF:4 +BRH:4 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol +FN:27,L1ForceOnlyReverseCustomGateway.registerTokenToL2 +FNDA:0,L1ForceOnlyReverseCustomGateway.registerTokenToL2 +DA:34,0 +FNF:1 +FNH:0 +LF:1 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol +FN:50,L1GatewayRouter.initialize +FNDA:4,L1GatewayRouter.initialize +DA:57,4 +DA:58,2 +DA:59,2 +DA:60,2 +FN:63,L1GatewayRouter.setDefaultGateway +FNDA:1,L1GatewayRouter.setDefaultGateway +DA:69,1 +DA:71,1 +DA:73,1 +DA:75,1 +BRDA:75,0,0,- +BRDA:75,0,1,1 +DA:76,1 +DA:79,1 +DA:84,1 +FN:100,L1GatewayRouter.setOwner +FNDA:258,L1GatewayRouter.setOwner +DA:101,257 +BRDA:101,1,0,1 +BRDA:101,1,1,256 +DA:103,256 +FN:106,L1GatewayRouter._setGateways +FNDA:7,L1GatewayRouter._setGateways +DA:114,7 +BRDA:114,2,0,- +BRDA:114,2,1,7 +DA:116,7 +DA:117,8 +DA:118,8 +DA:120,8 +BRDA:120,3,0,- +BRDA:120,3,1,6 +DA:124,7 +BRDA:124,4,0,1 +BRDA:124,4,1,6 +DA:128,6 +DA:132,6 +DA:138,6 +FN:162,L1GatewayRouter.setGateway +FNDA:1,L1GatewayRouter.setGateway +DA:168,1 +FN:180,L1GatewayRouter.setGateway +FNDA:7,L1GatewayRouter.setGateway +DA:187,8 +BRDA:187,5,0,1 +BRDA:187,5,1,7 +DA:192,7 +BRDA:192,6,0,1 +BRDA:192,6,1,6 +DA:194,6 +DA:195,6 +BRDA:195,7,0,1 +BRDA:195,7,1,- +DA:197,1 +BRDA:197,8,0,1 +BRDA:197,8,1,- +DA:200,5 +DA:201,5 +DA:203,5 +DA:204,5 +DA:206,5 +FN:217,L1GatewayRouter.setGateways +FNDA:3,L1GatewayRouter.setGateways +DA:226,2 +FN:230,L1GatewayRouter.outboundTransfer +FNDA:0,L1GatewayRouter.outboundTransfer +DA:238,0 +FN:259,L1GatewayRouter.outboundTransferCustomRefund +FNDA:0,L1GatewayRouter.outboundTransferCustomRefund +DA:268,0 +DA:269,0 +DA:274,0 +DA:276,0 +FN:294,L1GatewayRouter.supportsInterface +FNDA:256,L1GatewayRouter.supportsInterface +DA:302,256 +FNF:10 +FNH:8 +LF:40 +LH:35 +BRF:18 +BRH:13 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +FN:15,L1OrbitERC20Gateway._parseUserEncodedData +FNDA:5,L1OrbitERC20Gateway._parseUserEncodedData +DA:23,5 +FN:29,L1OrbitERC20Gateway._initiateDeposit +FNDA:2,L1OrbitERC20Gateway._initiateDeposit +DA:39,2 +FN:56,L1OrbitERC20Gateway._createRetryable +FNDA:2,L1OrbitERC20Gateway._createRetryable +DA:68,2 +FNF:3 +FNH:3 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol +FN:37,L1ReverseCustomGateway.inboundEscrowTransfer +FNDA:0,L1ReverseCustomGateway.inboundEscrowTransfer +DA:42,0 +FN:45,L1ReverseCustomGateway.outboundEscrowTransfer +FNDA:0,L1ReverseCustomGateway.outboundEscrowTransfer +DA:50,0 +DA:53,0 +FNF:2 +FNH:0 +LF:3 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol +FN:34,L1WethGateway.initialize +FNDA:0,L1WethGateway.initialize +DA:41,0 +DA:42,0 +BRDA:42,0,0,- +BRDA:42,0,1,- +DA:43,0 +BRDA:43,1,0,- +BRDA:43,1,1,- +DA:44,0 +DA:45,0 +FN:48,L1WethGateway.createOutboundTxCustomRefund +FNDA:0,L1WethGateway.createOutboundTxCustomRefund +DA:57,0 +FN:76,L1WethGateway.outboundEscrowTransfer +FNDA:0,L1WethGateway.outboundEscrowTransfer +DA:81,0 +DA:82,0 +DA:85,0 +FN:88,L1WethGateway.inboundEscrowTransfer +FNDA:0,L1WethGateway.inboundEscrowTransfer +DA:93,0 +DA:94,0 +FN:104,L1WethGateway.calculateL2TokenAddress +FNDA:0,L1WethGateway.calculateL2TokenAddress +DA:105,0 +BRDA:105,2,0,- +BRDA:105,2,1,- +DA:107,0 +DA:109,0 +FN:115,L1WethGateway.setRedirectedExit +FNDA:0,L1WethGateway.setRedirectedExit +DA:121,0 +FNF:6 +FNH:0 +LF:15 +LH:0 +BRF:6 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/AddressAliasHelper.sol +FN:28,AddressAliasHelper.applyL1ToL2Alias +FNDA:0,AddressAliasHelper.applyL1ToL2Alias +DA:30,0 +FN:38,AddressAliasHelper.undoL1ToL2Alias +FNDA:0,AddressAliasHelper.undoL1ToL2Alias +DA:40,0 +FNF:2 +FNH:0 +LF:2 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/BytesLib.sol +FN:15,BytesLib.toAddress +FNDA:0,BytesLib.toAddress +DA:16,0 +BRDA:16,0,0,- +BRDA:16,0,1,- +DA:17,0 +DA:20,0 +DA:23,0 +FN:26,BytesLib.toUint8 +FNDA:0,BytesLib.toUint8 +DA:27,0 +BRDA:27,1,0,- +BRDA:27,1,1,- +DA:28,0 +DA:31,0 +DA:34,0 +FN:37,BytesLib.toUint +FNDA:0,BytesLib.toUint +DA:38,0 +BRDA:38,2,0,- +BRDA:38,2,1,- +DA:39,0 +DA:42,0 +DA:45,0 +FN:48,BytesLib.toBytes32 +FNDA:0,BytesLib.toBytes32 +DA:49,0 +BRDA:49,3,0,- +BRDA:49,3,1,- +DA:50,0 +DA:53,0 +DA:56,0 +FNF:4 +FNH:0 +LF:16 +LH:0 +BRF:8 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/BytesParser.sol +FN:26,BytesParser.toUint8 +FNDA:0,BytesParser.toUint8 +DA:27,0 +BRDA:27,0,0,- +BRDA:27,0,1,- +DA:28,0 +DA:31,0 +DA:32,0 +BRDA:32,1,0,- +BRDA:32,1,1,- +DA:33,0 +DA:35,0 +DA:36,0 +FN:39,BytesParser.toString +FNDA:0,BytesParser.toString +DA:40,0 +BRDA:40,2,0,- +BRDA:40,2,1,- +DA:41,0 +DA:43,0 +BRDA:43,3,0,- +BRDA:43,3,1,- +DA:45,0 +BRDA:45,4,0,- +BRDA:45,4,1,- +DA:46,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:63,0 +DA:67,0 +DA:68,0 +FNF:2 +FNH:0 +LF:21 +LH:0 +BRF:10 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/ClonableBeaconProxy.sol +FN:27,BeaconProxyFactory.initialize +FNDA:0,BeaconProxyFactory.initialize +DA:28,0 +BRDA:28,0,0,- +BRDA:28,0,1,- +DA:29,0 +BRDA:29,1,0,- +BRDA:29,1,1,- +DA:30,0 +FN:33,BeaconProxyFactory.getSalt +FNDA:0,BeaconProxyFactory.getSalt +DA:34,0 +FN:37,BeaconProxyFactory.createProxy +FNDA:0,BeaconProxyFactory.createProxy +DA:39,0 +DA:40,0 +DA:41,0 +FN:44,BeaconProxyFactory.calculateExpectedAddress +FNDA:0,BeaconProxyFactory.calculateExpectedAddress +DA:49,0 +DA:50,0 +FN:53,BeaconProxyFactory.calculateExpectedAddress +FNDA:0,BeaconProxyFactory.calculateExpectedAddress +DA:54,0 +FNF:5 +FNH:0 +LF:10 +LH:0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/Cloneable.sol +FN:32,Cloneable.isMaster +FNDA:0,Cloneable.isMaster +DA:33,0 +FN:36,Cloneable.safeSelfDestruct +FNDA:0,Cloneable.safeSelfDestruct +DA:37,0 +BRDA:37,0,0,- +BRDA:37,0,1,- +DA:38,0 +FNF:2 +FNH:0 +LF:3 +LH:0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/ERC165.sol +FN:29,ERC165.supportsInterface +FNDA:768,ERC165.supportsInterface +DA:30,768 +FNF:1 +FNH:1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/ERC20Upgradeable.sol +FN:45,ERC20Upgradeable.__ERC20_init +FNDA:0,ERC20Upgradeable.__ERC20_init +DA:46,0 +FN:49,ERC20Upgradeable.__ERC20_init_unchained +FNDA:0,ERC20Upgradeable.__ERC20_init_unchained +DA:53,0 +DA:54,0 +DA:55,0 +FN:61,ERC20Upgradeable.name +FNDA:10,ERC20Upgradeable.name +DA:62,10 +FN:69,ERC20Upgradeable.symbol +FNDA:10,ERC20Upgradeable.symbol +DA:70,10 +FN:86,ERC20Upgradeable.decimals +FNDA:10,ERC20Upgradeable.decimals +DA:87,10 +FN:93,ERC20Upgradeable.totalSupply +FNDA:0,ERC20Upgradeable.totalSupply +DA:94,0 +FN:100,ERC20Upgradeable.balanceOf +FNDA:34,ERC20Upgradeable.balanceOf +DA:101,34 +FN:112,ERC20Upgradeable.transfer +FNDA:2,ERC20Upgradeable.transfer +DA:113,2 +DA:114,2 +DA:115,2 +FN:121,ERC20Upgradeable.allowance +FNDA:0,ERC20Upgradeable.allowance +DA:125,6 +FN:138,ERC20Upgradeable.approve +FNDA:4,ERC20Upgradeable.approve +DA:139,4 +DA:140,4 +DA:141,4 +FN:160,ERC20Upgradeable.transferFrom +FNDA:6,ERC20Upgradeable.transferFrom +DA:165,6 +DA:166,6 +DA:167,4 +DA:168,4 +FN:183,ERC20Upgradeable.increaseAllowance +FNDA:0,ERC20Upgradeable.increaseAllowance +DA:184,0 +DA:185,0 +DA:186,0 +FN:203,ERC20Upgradeable.decreaseAllowance +FNDA:0,ERC20Upgradeable.decreaseAllowance +DA:207,0 +DA:208,0 +DA:209,0 +BRDA:209,0,0,- +BRDA:209,0,1,- +DA:211,0 +DA:214,0 +FN:231,ERC20Upgradeable._transfer +FNDA:6,ERC20Upgradeable._transfer +DA:232,6 +BRDA:232,1,0,- +BRDA:232,1,1,6 +DA:233,6 +BRDA:233,2,0,- +BRDA:233,2,1,6 +DA:235,6 +DA:237,6 +DA:238,6 +BRDA:238,3,0,- +BRDA:238,3,1,6 +DA:240,6 +DA:243,6 +DA:246,6 +DA:248,6 +FN:260,ERC20Upgradeable._mint +FNDA:2,ERC20Upgradeable._mint +DA:261,2 +BRDA:261,4,0,- +BRDA:261,4,1,2 +DA:263,2 +DA:265,2 +DA:268,2 +DA:270,2 +DA:272,2 +FN:286,ERC20Upgradeable._burn +FNDA:0,ERC20Upgradeable._burn +DA:287,0 +BRDA:287,5,0,- +BRDA:287,5,1,- +DA:289,0 +DA:291,0 +DA:292,0 +BRDA:292,6,0,- +BRDA:292,6,1,- +DA:294,0 +DA:296,0 +DA:299,0 +DA:301,0 +FN:317,ERC20Upgradeable._approve +FNDA:8,ERC20Upgradeable._approve +DA:318,8 +BRDA:318,7,0,- +BRDA:318,7,1,8 +DA:319,8 +BRDA:319,8,0,- +BRDA:319,8,1,8 +DA:321,8 +DA:322,8 +FN:332,ERC20Upgradeable._setupDecimals +FNDA:0,ERC20Upgradeable._setupDecimals +DA:333,0 +FN:344,ERC20Upgradeable._spendAllowance +FNDA:6,ERC20Upgradeable._spendAllowance +DA:345,6 +DA:346,6 +BRDA:346,9,0,2 +BRDA:346,9,1,4 +DA:347,6 +BRDA:347,10,0,2 +BRDA:347,10,1,4 +DA:349,4 +FN:368,ERC20Upgradeable._beforeTokenTransfer +FNDA:8,ERC20Upgradeable._beforeTokenTransfer +FN:384,ERC20Upgradeable._afterTokenTransfer +FNDA:8,ERC20Upgradeable._afterTokenTransfer +FNF:21 +FNH:13 +LF:60 +LH:38 +BRF:22 +BRH:10 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/L2CustomGatewayToken.sol +FN:36,L2CustomGatewayToken.initialize +FNDA:0,L2CustomGatewayToken.initialize +DA:43,0 +FNF:1 +FNH:0 +LF:1 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/L2GatewayToken.sol +FN:46,L2GatewayToken._initialize +FNDA:0,L2GatewayToken._initialize +DA:53,0 +BRDA:53,0,0,- +BRDA:53,0,1,- +DA:54,0 +BRDA:54,1,0,- +BRDA:54,1,1,- +DA:55,0 +DA:56,0 +DA:58,0 +FN:66,L2GatewayToken.bridgeMint +FNDA:0,L2GatewayToken.bridgeMint +DA:67,0 +FN:76,L2GatewayToken.bridgeBurn +FNDA:0,L2GatewayToken.bridgeBurn +DA:77,0 +FNF:3 +FNH:0 +LF:7 +LH:0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/ProxyUtil.sol +FN:22,ProxyUtil.getProxyAdmin +FNDA:0,ProxyUtil.getProxyAdmin +DA:26,0 +DA:28,0 +FNF:1 +FNH:0 +LF:2 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/TransferAndCallToken.sol +FN:20,TransferAndCallToken.transferAndCall +FNDA:0,TransferAndCallToken.transferAndCall +DA:25,0 +DA:26,0 +DA:27,0 +BRDA:27,0,0,- +BRDA:27,0,1,- +DA:28,0 +DA:30,0 +FN:35,TransferAndCallToken.contractFallback +FNDA:0,TransferAndCallToken.contractFallback +DA:40,0 +DA:41,0 +FN:44,TransferAndCallToken.isContract +FNDA:0,TransferAndCallToken.isContract +DA:45,0 +DA:47,0 +DA:49,0 +FNF:3 +FNH:0 +LF:10 +LH:0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/Whitelist.sol +FN:33,WhitelistConsumer.updateWhitelistSource +FNDA:0,WhitelistConsumer.updateWhitelistSource +DA:34,0 +BRDA:34,0,0,- +BRDA:34,0,1,- +DA:35,0 +DA:36,0 +FN:56,Whitelist.setOwner +FNDA:0,Whitelist.setOwner +DA:57,0 +DA:58,0 +FN:61,Whitelist.setWhitelist +FNDA:0,Whitelist.setWhitelist +DA:62,0 +BRDA:62,0,0,- +BRDA:62,0,1,- +DA:64,0 +DA:65,0 +FN:70,Whitelist.triggerConsumers +FNDA:0,Whitelist.triggerConsumers +DA:71,0 +DA:72,0 +DA:74,0 +FNF:4 +FNH:0 +LF:11 +LH:0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/aeERC20.sol +FN:35,aeERC20._initialize +FNDA:0,aeERC20._initialize +DA:40,0 +DA:41,0 +DA:42,0 +FNF:1 +FNH:0 +LF:3 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/aeWETH.sol +FN:26,aeWETH.initialize +FNDA:0,aeWETH.initialize +DA:33,0 +FN:36,aeWETH.bridgeMint +FNDA:0,aeWETH.bridgeMint +DA:41,0 +FN:44,aeWETH.bridgeBurn +FNDA:0,aeWETH.bridgeBurn +DA:45,0 +DA:46,0 +DA:47,0 +BRDA:47,0,0,- +BRDA:47,0,1,- +FN:50,aeWETH.deposit +FNDA:0,aeWETH.deposit +DA:51,0 +FN:54,aeWETH.withdraw +FNDA:0,aeWETH.withdraw +DA:55,0 +FN:58,aeWETH.depositTo +FNDA:0,aeWETH.depositTo +DA:59,0 +FN:62,aeWETH.withdrawTo +FNDA:0,aeWETH.withdrawTo +DA:63,0 +DA:64,0 +DA:65,0 +BRDA:65,1,0,- +BRDA:65,1,1,- +FNF:7 +FNH:0 +LF:11 +LH:0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/draft-ERC20PermitUpgradeable.sol +FN:50,ERC20PermitUpgradeable.__ERC20Permit_init +FNDA:0,ERC20PermitUpgradeable.__ERC20Permit_init +DA:51,0 +FN:54,ERC20PermitUpgradeable.__ERC20Permit_init_unchained +FNDA:0,ERC20PermitUpgradeable.__ERC20Permit_init_unchained +FN:59,ERC20PermitUpgradeable.permit +FNDA:0,ERC20PermitUpgradeable.permit +DA:68,0 +BRDA:68,0,0,- +BRDA:68,0,1,- +DA:70,0 +DA:74,0 +DA:76,0 +DA:77,0 +BRDA:77,1,0,- +BRDA:77,1,1,- +DA:79,0 +FN:85,ERC20PermitUpgradeable.nonces +FNDA:0,ERC20PermitUpgradeable.nonces +DA:86,0 +FN:93,ERC20PermitUpgradeable.DOMAIN_SEPARATOR +FNDA:0,ERC20PermitUpgradeable.DOMAIN_SEPARATOR +DA:94,0 +FN:102,ERC20PermitUpgradeable._useNonce +FNDA:0,ERC20PermitUpgradeable._useNonce +DA:103,0 +DA:104,0 +DA:105,0 +FNF:6 +FNH:0 +LF:12 +LH:0 +BRF:4 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/gateway/GatewayMessageHandler.sol +FN:25,GatewayMessageHandler.encodeToL2GatewayMsg +FNDA:0,GatewayMessageHandler.encodeToL2GatewayMsg +DA:30,0 +FN:33,GatewayMessageHandler.parseFromL1GatewayMsg +FNDA:0,GatewayMessageHandler.parseFromL1GatewayMsg +DA:39,0 +FN:44,GatewayMessageHandler.encodeFromL2GatewayMsg +FNDA:0,GatewayMessageHandler.encodeFromL2GatewayMsg +DA:49,0 +FN:52,GatewayMessageHandler.parseToL1GatewayMsg +FNDA:0,GatewayMessageHandler.parseToL1GatewayMsg +DA:58,0 +FN:63,GatewayMessageHandler.encodeFromRouterToGateway +FNDA:0,GatewayMessageHandler.encodeFromRouterToGateway +DA:69,0 +FN:72,GatewayMessageHandler.parseFromRouterToGateway +FNDA:0,GatewayMessageHandler.parseFromRouterToGateway +DA:78,0 +FNF:6 +FNH:0 +LF:6 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/gateway/GatewayRouter.sol +FN:39,GatewayRouter.postUpgradeInit +FNDA:1,GatewayRouter.postUpgradeInit +DA:42,1 +DA:43,1 +BRDA:43,0,0,1 +BRDA:43,0,1,- +FN:47,GatewayRouter._initialize +FNDA:4,GatewayRouter._initialize +DA:53,4 +BRDA:53,1,0,- +BRDA:53,1,1,4 +DA:54,4 +DA:56,2 +FN:59,GatewayRouter.finalizeInboundTransfer +FNDA:0,GatewayRouter.finalizeInboundTransfer +DA:66,0 +FN:69,GatewayRouter.outboundTransfer +FNDA:0,GatewayRouter.outboundTransfer +DA:79,0 +DA:80,0 +DA:85,0 +DA:86,0 +FN:97,GatewayRouter.getOutboundCalldata +FNDA:0,GatewayRouter.getOutboundCalldata +DA:104,0 +DA:105,0 +FN:108,GatewayRouter.getGateway +FNDA:0,GatewayRouter.getGateway +DA:109,6 +DA:111,6 +BRDA:111,2,0,5 +BRDA:111,2,1,6 +DA:113,5 +DA:116,6 +BRDA:116,3,0,5 +BRDA:116,3,1,1 +DA:118,5 +DA:121,0 +FN:124,GatewayRouter.calculateL2TokenAddress +FNDA:0,GatewayRouter.calculateL2TokenAddress +DA:131,0 +DA:132,0 +BRDA:132,4,0,- +BRDA:132,4,1,- +DA:133,0 +DA:135,0 +FNF:7 +FNH:2 +LF:22 +LH:10 +BRF:10 +BRH:6 +end_of_record +TN: +SF:contracts/tokenbridge/libraries/gateway/TokenGateway.sol +FN:36,TokenGateway._initialize +FNDA:17,TokenGateway._initialize +DA:40,17 +BRDA:40,0,0,1 +BRDA:40,0,1,16 +DA:41,16 +BRDA:41,1,0,1 +BRDA:41,1,1,15 +DA:42,15 +DA:43,15 +FN:46,TokenGateway.isRouter +FNDA:22,TokenGateway.isRouter +DA:47,22 +FNF:2 +FNH:2 +LF:5 +LH:5 +BRF:4 +BRH:4 +end_of_record +TN: +SF:contracts/tokenbridge/test/AddressMappingTest.sol +FN:25,AddressMappingTest.getL1AddressTest +FNDA:0,AddressMappingTest.getL1AddressTest +DA:26,0 +FNF:1 +FNH:0 +LF:1 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/test/ArbSysMock.sol +FN:7,ArbSysMock.sendTxToL1 +FNDA:0,ArbSysMock.sendTxToL1 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +FNF:1 +FNH:0 +LF:4 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/test/InboxMock.sol +FN:49,InboxMock.createRetryableTicket +FNDA:15,InboxMock.createRetryableTicket +DA:59,15 +BRDA:59,0,0,- +BRDA:59,0,1,15 +DA:60,0 +DA:62,15 +DA:63,15 +DA:64,15 +DA:65,15 +FN:31,AbsInboxMock.bridge +FNDA:14,AbsInboxMock.bridge +DA:32,14 +FN:35,AbsInboxMock.activeOutbox +FNDA:4,AbsInboxMock.activeOutbox +DA:36,4 +FN:39,AbsInboxMock.setL2ToL1Sender +FNDA:4,AbsInboxMock.setL2ToL1Sender +DA:40,4 +FN:43,AbsInboxMock.l2ToL1Sender +FNDA:4,AbsInboxMock.l2ToL1Sender +DA:44,4 +FN:80,ERC20InboxMock.createRetryableTicket +FNDA:2,ERC20InboxMock.createRetryableTicket +DA:92,2 +BRDA:92,0,0,- +BRDA:92,0,1,2 +DA:93,0 +DA:96,2 +DA:97,2 +DA:98,2 +DA:107,2 +FNF:6 +FNH:6 +LF:16 +LH:14 +BRF:4 +BRH:2 +end_of_record +TN: +SF:contracts/tokenbridge/test/TestArbCustomToken.sol +FN:54,MintableTestArbCustomToken.userMint +FNDA:0,MintableTestArbCustomToken.userMint +DA:55,0 +FN:40,TestArbCustomToken.someWackyCustomStuff +FNDA:0,TestArbCustomToken.someWackyCustomStuff +FN:42,TestArbCustomToken.bridgeMint +FNDA:0,TestArbCustomToken.bridgeMint +DA:43,0 +FN:46,TestArbCustomToken.bridgeBurn +FNDA:0,TestArbCustomToken.bridgeBurn +DA:47,0 +FN:74,ReverseTestArbCustomToken.someWackyCustomStuff +FNDA:0,ReverseTestArbCustomToken.someWackyCustomStuff +FN:76,ReverseTestArbCustomToken.mint +FNDA:0,ReverseTestArbCustomToken.mint +DA:77,0 +FNF:6 +FNH:0 +LF:4 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/test/TestArbCustomTokenBurnFee.sol +FN:31,TestArbCustomTokenBurnFee._burn +FNDA:0,TestArbCustomTokenBurnFee._burn +DA:32,0 +DA:33,0 +FNF:1 +FNH:0 +LF:2 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/test/TestBytesParser.sol +FN:24,TestBytesParser.bytesToString +FNDA:0,TestBytesParser.bytesToString +DA:29,0 +FN:32,TestBytesParser.bytesToUint8 +FNDA:0,TestBytesParser.bytesToUint8 +DA:33,0 +FNF:2 +FNH:0 +LF:2 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/test/TestCustomTokenL1.sol +FN:144,ReverseTestCustomTokenL1.bridgeBurn +FNDA:0,ReverseTestCustomTokenL1.bridgeBurn +DA:149,0 +FN:152,ReverseTestCustomTokenL1.balanceOf +FNDA:0,ReverseTestCustomTokenL1.balanceOf +DA:158,0 +FN:161,ReverseTestCustomTokenL1.transferFrom +FNDA:0,ReverseTestCustomTokenL1.transferFrom +DA:166,0 +FN:114,MintableTestCustomTokenL1.bridgeMint +FNDA:0,MintableTestCustomTokenL1.bridgeMint +DA:119,0 +FN:122,MintableTestCustomTokenL1.balanceOf +FNDA:0,MintableTestCustomTokenL1.balanceOf +DA:129,0 +FN:132,MintableTestCustomTokenL1.transferFrom +FNDA:0,MintableTestCustomTokenL1.transferFrom +DA:137,0 +FN:43,TestCustomTokenL1.mint +FNDA:0,TestCustomTokenL1.mint +DA:44,0 +FN:47,TestCustomTokenL1.transferFrom +FNDA:0,TestCustomTokenL1.transferFrom +DA:52,0 +FN:55,TestCustomTokenL1.balanceOf +FNDA:0,TestCustomTokenL1.balanceOf +DA:62,0 +FN:66,TestCustomTokenL1.isArbitrumEnabled +FNDA:0,TestCustomTokenL1.isArbitrumEnabled +DA:67,0 +BRDA:67,0,0,- +BRDA:67,0,1,- +DA:68,0 +FN:71,TestCustomTokenL1.registerTokenOnL2 +FNDA:0,TestCustomTokenL1.registerTokenOnL2 +DA:83,0 +DA:84,0 +DA:86,0 +DA:94,0 +DA:102,0 +FNF:11 +FNH:0 +LF:16 +LH:0 +BRF:2 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/test/TestERC20.sol +FN:28,TestERC20.mint +FNDA:2,TestERC20.mint +DA:29,2 +FN:38,Bytes32ERC20.transfer +FNDA:0,Bytes32ERC20.transfer +DA:39,0 +FN:42,Bytes32ERC20.transferFrom +FNDA:0,Bytes32ERC20.transferFrom +DA:47,0 +BRDA:47,0,0,- +BRDA:47,0,1,- +DA:48,0 +DA:51,0 +DA:52,0 +DA:54,0 +FN:57,Bytes32ERC20.approve +FNDA:0,Bytes32ERC20.approve +DA:58,0 +DA:59,0 +FN:62,Bytes32ERC20.mint +FNDA:0,Bytes32ERC20.mint +DA:63,0 +FNF:5 +FNH:1 +LF:10 +LH:1 +BRF:2 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/test/TestPostDepositCall.sol +FN:29,L2Called.postDepositHook +FNDA:0,L2Called.postDepositHook +DA:30,0 +FN:33,L2Called.onTokenTransfer +FNDA:0,L2Called.onTokenTransfer +DA:38,0 +DA:40,0 +BRDA:40,0,0,- +BRDA:40,0,1,- +DA:41,0 +DA:42,0 +BRDA:42,1,0,- +BRDA:42,1,1,- +DA:43,0 +DA:44,0 +BRDA:44,2,0,- +BRDA:44,2,1,- +DA:46,0 +DA:48,0 +FNF:2 +FNH:0 +LF:9 +LH:0 +BRF:6 +BRH:0 +end_of_record +TN: +SF:contracts/tokenbridge/test/TestWETH9.sol +FN:12,TestWETH9.deposit +FNDA:0,TestWETH9.deposit +DA:13,0 +FN:16,TestWETH9.withdraw +FNDA:0,TestWETH9.withdraw +DA:17,0 +DA:18,0 +FNF:2 +FNH:0 +LF:3 +LH:0 +BRF:0 +BRH:0 +end_of_record +TN: +SF:test-foundry/L1ArbitrumExtendedGateway.t.sol +FN:315,TestExitReceiver.onExitTransfer +FNDA:3072,TestExitReceiver.onExitTransfer +DA:320,3072 +DA:321,3072 +FNF:1 +FNH:1 +LF:2 +LH:2 +BRF:0 +BRH:0 +end_of_record diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 9ed9573271..0286a16a25 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -8,6 +8,7 @@ import { L2GatewayRouter } from "contracts/tokenbridge/arbitrum/gateway/L2Gatewa import { L1ERC20Gateway } from "contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol"; import { L1CustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol"; import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; +import { IERC165 } from "contracts/tokenbridge/libraries/IERC165.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract L1GatewayRouterTest is GatewayRouterTest { @@ -560,6 +561,11 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } + function test_setGateways_revert_notOwner() public { + vm.expectRevert("ONLY_OWNER"); + l1Router.setGateways{ value: 1000 }(new address[](1), new address[](1), 100, 8, 10); + } + function test_setOwner(address newOwner) public { vm.assume(newOwner != address(0)); @@ -585,6 +591,18 @@ contract L1GatewayRouterTest is GatewayRouterTest { l1Router.setOwner(address(300)); } + function test_supportsInterface(bytes4 iface) public { + bool expected = false; + if ( + iface == type(IERC165).interfaceId || + iface == L1GatewayRouter.outboundTransferCustomRefund.selector + ) { + expected = true; + } + + assertEq(l1Router.supportsInterface(iface), expected, "Interface shouldn't be supported"); + } + //// // Event declarations //// From fc11760c55ef535378a4d4098c5ca89d62c27646 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 28 Apr 2023 11:43:23 +0200 Subject: [PATCH 047/163] Test router's outboundTransfer --- test-foundry/L1GatewayRouter.t.sol | 192 ++++++++++++++++++++++++----- 1 file changed, 164 insertions(+), 28 deletions(-) diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 0286a16a25..913a629da4 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -10,15 +10,23 @@ import { L1CustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1Custom import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; import { IERC165 } from "contracts/tokenbridge/libraries/IERC165.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20PresetMinterPauser } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; contract L1GatewayRouterTest is GatewayRouterTest { L1GatewayRouter public l1Router; address public owner = makeAddr("owner"); + address public user = makeAddr("user"); address public defaultGateway; address public counterpartGateway = makeAddr("counterpartGateway"); address public inbox; + // retryable params + uint256 public maxSubmissionCost = 50000; + uint256 public maxGas = 1000000000; + uint256 public gasPriceBid = 3; + uint256 public retryableCost = maxSubmissionCost + maxGas * gasPriceBid; + function setUp() public { inbox = address(new InboxMock()); @@ -28,6 +36,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { defaultGateway = address(new L1ERC20Gateway()); vm.deal(owner, 100 ether); + vm.deal(user, 100 ether); } /* solhint-disable func-name-mixedcase */ @@ -74,12 +83,6 @@ contract L1GatewayRouterTest is GatewayRouterTest { makeAddr("l2BeaconProxyFactory") ); - // retryable params - uint256 maxSubmissionCost = 50000; - uint256 maxGas = 1000000000; - uint256 gasPriceBid = 3; - uint256 retryableCost = maxSubmissionCost + maxGas * gasPriceBid; - // event checkers vm.expectEmit(true, true, true, true); emit DefaultGatewayUpdated(address(newL1DefaultGateway)); @@ -147,13 +150,10 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); // set gateway params - uint256 maxSubmissionCost = 40000; - uint256 maxGas = 1000000000; - uint256 gasPrice = 3; - uint256 value = maxSubmissionCost + maxGas * gasPrice; address creditBackAddress = makeAddr("creditBackAddress"); // expect events + vm.expectEmit(true, true, true, true); emit GatewaySet(address(customToken), address(customGateway)); vm.expectEmit(true, true, true, true); @@ -177,10 +177,10 @@ contract L1GatewayRouterTest is GatewayRouterTest { // set gateway vm.prank(address(customToken)); - uint256 seqNum = l1Router.setGateway{ value: value }( + uint256 seqNum = l1Router.setGateway{ value: retryableCost }( address(customGateway), maxGas, - gasPrice, + gasPriceBid, maxSubmissionCost, creditBackAddress ); @@ -228,6 +228,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { uint256 value = maxSubmissionCost + maxGas * gasPrice; // expect events + vm.expectEmit(true, true, true, true); emit GatewaySet(address(customToken), address(customGateway)); vm.expectEmit(true, true, true, true); @@ -251,10 +252,10 @@ contract L1GatewayRouterTest is GatewayRouterTest { // set gateway vm.prank(address(customToken)); - uint256 seqNum = l1Router.setGateway{ value: value }( + uint256 seqNum = l1Router.setGateway{ value: retryableCost }( address(customGateway), maxGas, - gasPrice, + gasPriceBid, maxSubmissionCost ); @@ -336,20 +337,20 @@ contract L1GatewayRouterTest is GatewayRouterTest { // register token to gateway vm.prank(token); - L1CustomGateway(initialGateway).registerTokenToL2{ value: value }( + L1CustomGateway(initialGateway).registerTokenToL2{ value: retryableCost }( makeAddr("tokenL2Address"), maxGas, - gasPrice, + gasPriceBid, maxSubmissionCost, creditBackAddress ); // initially set gateway for token vm.prank(address(token)); - l1Router.setGateway{ value: value }( + l1Router.setGateway{ value: retryableCost }( initialGateway, maxGas, - gasPrice, + gasPriceBid, maxSubmissionCost, creditBackAddress ); @@ -360,10 +361,10 @@ contract L1GatewayRouterTest is GatewayRouterTest { vm.prank(token); vm.expectRevert("NO_UPDATE_TO_DIFFERENT_ADDR"); - l1Router.setGateway{ value: value }( + l1Router.setGateway{ value: retryableCost }( newGateway, maxGas, - gasPrice, + gasPriceBid, maxSubmissionCost, creditBackAddress ); @@ -434,7 +435,9 @@ contract L1GatewayRouterTest is GatewayRouterTest { } // expect events + vm.expectEmit(true, true, true, true); emit GatewaySet(tokens[0], gateways[0]); + vm.expectEmit(true, true, true, true); emit GatewaySet(tokens[1], gateways[1]); vm.expectEmit(true, true, true, true); @@ -457,11 +460,11 @@ contract L1GatewayRouterTest is GatewayRouterTest { /// set gateways vm.prank(owner); - uint256 seqNum = l1Router.setGateways{ value: value }( + uint256 seqNum = l1Router.setGateways{ value: retryableCost }( tokens, gateways, maxGas, - gasPrice, + gasPriceBid, maxSubmissionCost ); @@ -501,20 +504,20 @@ contract L1GatewayRouterTest is GatewayRouterTest { // register token to gateway vm.prank(token); - L1CustomGateway(initialGateway).registerTokenToL2{ value: value }( + L1CustomGateway(initialGateway).registerTokenToL2{ value: retryableCost }( makeAddr("tokenL2Address"), maxGas, - gasPrice, + gasPriceBid, maxSubmissionCost, creditBackAddress ); // initially set gateway for token vm.prank(address(token)); - l1Router.setGateway{ value: value }( + l1Router.setGateway{ value: retryableCost }( initialGateway, maxGas, - gasPrice, + gasPriceBid, maxSubmissionCost, creditBackAddress ); @@ -524,6 +527,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { address newGateway = address(0); // expect events + vm.expectEmit(true, true, true, true); emit GatewaySet(token, newGateway); vm.expectEmit(true, true, true, true); @@ -547,11 +551,11 @@ contract L1GatewayRouterTest is GatewayRouterTest { /// set gateways vm.prank(owner); - uint256 seqNum = l1Router.setGateways{ value: value }( + uint256 seqNum = l1Router.setGateways{ value: retryableCost }( _tokenArr, _gatewayArr, maxGas, - gasPrice, + gasPriceBid, maxSubmissionCost ); @@ -603,9 +607,141 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(l1Router.supportsInterface(iface), expected, "Interface shouldn't be supported"); } + function test_outboundTransfer() public { + // init default gateway + L1ERC20Gateway(defaultGateway).initialize( + makeAddr("defaultGatewayCounterpart"), + address(l1Router), + inbox, + 0x0000000000000000000000000000000000000000000000000000000000000001, + makeAddr("l2BeaconProxyFactory") + ); + + // set default gateway + vm.prank(owner); + l1Router.setDefaultGateway{ value: retryableCost }( + address(defaultGateway), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + + // create token + ERC20PresetMinterPauser token = new ERC20PresetMinterPauser("X", "Y"); + token.mint(user, 10000); + vm.prank(user); + token.approve(defaultGateway, 103); + + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(defaultGateway)); + + /// deposit data + address to = address(401); + uint256 amount = 103; + bytes memory callHookData = ""; + bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); + + // expect event + vm.expectEmit(true, true, true, true); + emit TransferRouted(address(token), user, to, address(defaultGateway)); + + /// deposit it + vm.prank(user); + l1Router.outboundTransfer{ value: retryableCost }( + address(token), + to, + amount, + maxGas, + gasPriceBid, + userEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, amount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(defaultGateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + amount, + "Wrong defaultGateway balance" + ); + } + + function test_outboundTransferCustomRefund() public { + // init default gateway + L1ERC20Gateway(defaultGateway).initialize( + makeAddr("defaultGatewayCounterpart"), + address(l1Router), + inbox, + 0x0000000000000000000000000000000000000000000000000000000000000001, + makeAddr("l2BeaconProxyFactory") + ); + + // set default gateway + vm.prank(owner); + l1Router.setDefaultGateway{ value: retryableCost }( + address(defaultGateway), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + + // create token + ERC20PresetMinterPauser token = new ERC20PresetMinterPauser("X", "Y"); + token.mint(user, 10000); + vm.prank(user); + token.approve(defaultGateway, 103); + + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(defaultGateway)); + + /// deposit data + address refundTo = address(400); + address to = address(401); + uint256 amount = 103; + bytes memory callHookData = ""; + bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); + + // expect event + vm.expectEmit(true, true, true, true); + emit TransferRouted(address(token), user, to, address(defaultGateway)); + + /// deposit it + vm.prank(user); + l1Router.outboundTransferCustomRefund{ value: retryableCost }( + address(token), + refundTo, + to, + amount, + maxGas, + gasPriceBid, + userEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, amount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(defaultGateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + amount, + "Wrong defaultGateway balance" + ); + } + //// // Event declarations //// + event TransferRouted( + address indexed token, + address indexed _userFrom, + address indexed _userTo, + address gateway + ); event GatewaySet(address indexed l1Token, address indexed gateway); event DefaultGatewayUpdated(address newDefaultGateway); From 6598054090a54cd942ca301d00f8c0ecd50f571e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 28 Apr 2023 12:00:03 +0200 Subject: [PATCH 048/163] Add more coverage --- .../MulticallV2.sol.func-sort-c.html | 189 -- .../rpc-utils/MulticallV2.sol.func.html | 189 -- .../rpc-utils/MulticallV2.sol.gcov.html | 333 --- .../contracts/rpc-utils/index-sort-b.html | 107 - .../contracts/rpc-utils/index-sort-f.html | 107 - .../contracts/rpc-utils/index-sort-l.html | 107 - .../contracts/rpc-utils/index.html | 107 - ...trumExtendedGateway.t.sol.func-sort-c.html | 85 - .../L1ArbitrumExtendedGateway.t.sol.func.html | 85 - .../L1ArbitrumExtendedGateway.t.sol.gcov.html | 408 ---- .../test-foundry/index-sort-b.html | 107 - .../test-foundry/index-sort-f.html | 107 - .../test-foundry/index-sort-l.html | 107 - .../test-foundry/index.html | 107 - coverage/amber.png | Bin 141 -> 0 bytes .../L2ArbitrumMessenger.sol.func-sort-c.html | 85 - .../L2ArbitrumMessenger.sol.func.html | 85 - .../L2ArbitrumMessenger.sol.gcov.html | 125 -- .../ReverseArbToken.sol.func-sort-c.html | 89 - .../arbitrum/ReverseArbToken.sol.func.html | 89 - .../arbitrum/ReverseArbToken.sol.gcov.html | 125 -- .../StandardArbERC20.sol.func-sort-c.html | 97 - .../arbitrum/StandardArbERC20.sol.func.html | 97 - .../arbitrum/StandardArbERC20.sol.gcov.html | 183 -- .../L2ArbitrumGateway.sol.func-sort-c.html | 117 -- .../gateway/L2ArbitrumGateway.sol.func.html | 117 -- .../gateway/L2ArbitrumGateway.sol.gcov.html | 384 ---- .../L2CustomGateway.sol.func-sort-c.html | 97 - .../gateway/L2CustomGateway.sol.func.html | 97 - .../gateway/L2CustomGateway.sol.gcov.html | 160 -- .../L2ERC20Gateway.sol.func-sort-c.html | 101 - .../gateway/L2ERC20Gateway.sol.func.html | 101 - .../gateway/L2ERC20Gateway.sol.gcov.html | 186 -- .../L2GatewayRouter.sol.func-sort-c.html | 97 - .../gateway/L2GatewayRouter.sol.func.html | 97 - .../gateway/L2GatewayRouter.sol.gcov.html | 154 -- ...2ReverseCustomGateway.sol.func-sort-c.html | 89 - .../L2ReverseCustomGateway.sol.func.html | 89 - .../L2ReverseCustomGateway.sol.gcov.html | 146 -- .../L2WethGateway.sol.func-sort-c.html | 101 - .../gateway/L2WethGateway.sol.func.html | 101 - .../gateway/L2WethGateway.sol.gcov.html | 192 -- coverage/arbitrum/gateway/index-sort-b.html | 167 -- coverage/arbitrum/gateway/index-sort-f.html | 167 -- coverage/arbitrum/gateway/index-sort-l.html | 167 -- coverage/arbitrum/gateway/index.html | 167 -- coverage/arbitrum/index-sort-b.html | 131 -- coverage/arbitrum/index-sort-f.html | 131 -- coverage/arbitrum/index-sort-l.html | 131 -- coverage/arbitrum/index.html | 131 -- coverage/emerald.png | Bin 141 -> 0 bytes .../L1ArbitrumMessenger.sol.func-sort-c.html | 101 - .../L1ArbitrumMessenger.sol.func.html | 101 - .../L1ArbitrumMessenger.sol.gcov.html | 302 --- ...bitrumExtendedGateway.sol.func-sort-c.html | 97 - .../L1ArbitrumExtendedGateway.sol.func.html | 97 - .../L1ArbitrumExtendedGateway.sol.gcov.html | 223 -- .../L1ArbitrumGateway.sol.func-sort-c.html | 137 -- .../gateway/L1ArbitrumGateway.sol.func.html | 137 -- .../gateway/L1ArbitrumGateway.sol.gcov.html | 488 ----- .../L1CustomGateway.sol.func-sort-c.html | 109 - .../gateway/L1CustomGateway.sol.func.html | 109 - .../gateway/L1CustomGateway.sol.gcov.html | 328 --- .../L1ERC20Gateway.sol.func-sort-c.html | 109 - .../gateway/L1ERC20Gateway.sol.func.html | 109 - .../gateway/L1ERC20Gateway.sol.gcov.html | 246 --- ...yReverseCustomGateway.sol.func-sort-c.html | 85 - ...orceOnlyReverseCustomGateway.sol.func.html | 85 - ...orceOnlyReverseCustomGateway.sol.gcov.html | 121 -- .../L1GatewayRouter.sol.func-sort-c.html | 117 -- .../gateway/L1GatewayRouter.sol.func.html | 117 -- .../gateway/L1GatewayRouter.sol.gcov.html | 391 ---- .../L1OrbitERC20Gateway.sol.func-sort-c.html | 93 - .../gateway/L1OrbitERC20Gateway.sol.func.html | 93 - .../gateway/L1OrbitERC20Gateway.sol.gcov.html | 166 -- ...1ReverseCustomGateway.sol.func-sort-c.html | 89 - .../L1ReverseCustomGateway.sol.func.html | 89 - .../L1ReverseCustomGateway.sol.gcov.html | 140 -- .../L1WethGateway.sol.func-sort-c.html | 105 - .../gateway/L1WethGateway.sol.func.html | 105 - .../gateway/L1WethGateway.sol.gcov.html | 210 -- coverage/ethereum/gateway/index-sort-b.html | 203 -- coverage/ethereum/gateway/index-sort-f.html | 203 -- coverage/ethereum/gateway/index-sort-l.html | 203 -- coverage/ethereum/gateway/index.html | 203 -- coverage/ethereum/index-sort-b.html | 107 - coverage/ethereum/index-sort-f.html | 107 - coverage/ethereum/index-sort-l.html | 107 - coverage/ethereum/index.html | 107 - coverage/gcov.css | 519 ----- coverage/glass.png | Bin 167 -> 0 bytes coverage/index-sort-b.html | 203 -- coverage/index-sort-f.html | 203 -- coverage/index-sort-l.html | 203 -- coverage/index.html | 203 -- .../AddressAliasHelper.sol.func-sort-c.html | 89 - .../AddressAliasHelper.sol.func.html | 89 - .../AddressAliasHelper.sol.gcov.html | 128 -- .../libraries/BytesLib.sol.func-sort-c.html | 97 - coverage/libraries/BytesLib.sol.func.html | 97 - coverage/libraries/BytesLib.sol.gcov.html | 144 -- .../BytesParser.sol.func-sort-c.html | 89 - coverage/libraries/BytesParser.sol.func.html | 89 - coverage/libraries/BytesParser.sol.gcov.html | 156 -- .../ClonableBeaconProxy.sol.func-sort-c.html | 97 - .../ClonableBeaconProxy.sol.func.html | 97 - .../ClonableBeaconProxy.sol.gcov.html | 141 -- .../libraries/Cloneable.sol.func-sort-c.html | 89 - coverage/libraries/Cloneable.sol.func.html | 89 - coverage/libraries/Cloneable.sol.gcov.html | 125 -- .../libraries/ERC165.sol.func-sort-c.html | 85 - coverage/libraries/ERC165.sol.func.html | 85 - coverage/libraries/ERC165.sol.gcov.html | 117 -- .../ERC20Upgradeable.sol.func-sort-c.html | 165 -- .../libraries/ERC20Upgradeable.sol.func.html | 165 -- .../libraries/ERC20Upgradeable.sol.gcov.html | 477 ----- .../L2CustomGatewayToken.sol.func-sort-c.html | 85 - .../L2CustomGatewayToken.sol.func.html | 85 - .../L2CustomGatewayToken.sol.gcov.html | 130 -- .../L2GatewayToken.sol.func-sort-c.html | 93 - .../libraries/L2GatewayToken.sol.func.html | 93 - .../libraries/L2GatewayToken.sol.gcov.html | 164 -- .../libraries/ProxyUtil.sol.func-sort-c.html | 85 - coverage/libraries/ProxyUtil.sol.func.html | 85 - coverage/libraries/ProxyUtil.sol.gcov.html | 116 -- .../TransferAndCallToken.sol.func-sort-c.html | 93 - .../TransferAndCallToken.sol.func.html | 93 - .../TransferAndCallToken.sol.gcov.html | 136 -- .../libraries/Whitelist.sol.func-sort-c.html | 97 - coverage/libraries/Whitelist.sol.func.html | 97 - coverage/libraries/Whitelist.sol.gcov.html | 161 -- .../libraries/aeERC20.sol.func-sort-c.html | 85 - coverage/libraries/aeERC20.sol.func.html | 85 - coverage/libraries/aeERC20.sol.gcov.html | 129 -- .../libraries/aeWETH.sol.func-sort-c.html | 109 - coverage/libraries/aeWETH.sol.func.html | 109 - coverage/libraries/aeWETH.sol.gcov.html | 156 -- ...RC20PermitUpgradeable.sol.func-sort-c.html | 105 - ...draft-ERC20PermitUpgradeable.sol.func.html | 105 - ...draft-ERC20PermitUpgradeable.sol.gcov.html | 199 -- ...GatewayMessageHandler.sol.func-sort-c.html | 105 - .../GatewayMessageHandler.sol.func.html | 105 - .../GatewayMessageHandler.sol.gcov.html | 165 -- .../GatewayRouter.sol.func-sort-c.html | 109 - .../gateway/GatewayRouter.sol.func.html | 109 - .../gateway/GatewayRouter.sol.gcov.html | 222 -- .../gateway/TokenGateway.sol.func-sort-c.html | 89 - .../gateway/TokenGateway.sol.func.html | 89 - .../gateway/TokenGateway.sol.gcov.html | 148 -- coverage/libraries/gateway/index-sort-b.html | 131 -- coverage/libraries/gateway/index-sort-f.html | 131 -- coverage/libraries/gateway/index-sort-l.html | 131 -- coverage/libraries/gateway/index.html | 131 -- coverage/libraries/index-sort-b.html | 275 --- coverage/libraries/index-sort-f.html | 275 --- coverage/libraries/index-sort-l.html | 275 --- coverage/libraries/index.html | 275 --- coverage/ruby.png | Bin 141 -> 0 bytes coverage/snow.png | Bin 141 -> 0 bytes .../AddressMappingTest.sol.func-sort-c.html | 85 - .../test/AddressMappingTest.sol.func.html | 85 - .../test/AddressMappingTest.sol.gcov.html | 113 -- coverage/test/ArbSysMock.sol.func-sort-c.html | 85 - coverage/test/ArbSysMock.sol.func.html | 85 - coverage/test/ArbSysMock.sol.gcov.html | 102 - coverage/test/InboxMock.sol.func-sort-c.html | 105 - coverage/test/InboxMock.sol.func.html | 105 - coverage/test/InboxMock.sol.gcov.html | 194 -- .../TestArbCustomToken.sol.func-sort-c.html | 105 - .../test/TestArbCustomToken.sol.func.html | 105 - .../test/TestArbCustomToken.sol.gcov.html | 164 -- ...ArbCustomTokenBurnFee.sol.func-sort-c.html | 85 - .../TestArbCustomTokenBurnFee.sol.func.html | 85 - .../TestArbCustomTokenBurnFee.sol.gcov.html | 120 -- .../test/TestBytesParser.sol.func-sort-c.html | 89 - coverage/test/TestBytesParser.sol.func.html | 89 - coverage/test/TestBytesParser.sol.gcov.html | 120 -- .../TestCustomTokenL1.sol.func-sort-c.html | 125 -- coverage/test/TestCustomTokenL1.sol.func.html | 125 -- coverage/test/TestCustomTokenL1.sol.gcov.html | 253 --- coverage/test/TestERC20.sol.func-sort-c.html | 101 - coverage/test/TestERC20.sol.func.html | 101 - coverage/test/TestERC20.sol.gcov.html | 160 -- .../TestPostDepositCall.sol.func-sort-c.html | 89 - .../test/TestPostDepositCall.sol.func.html | 89 - .../test/TestPostDepositCall.sol.gcov.html | 136 -- coverage/test/TestWETH9.sol.func-sort-c.html | 89 - coverage/test/TestWETH9.sol.func.html | 89 - coverage/test/TestWETH9.sol.gcov.html | 105 - coverage/test/index-sort-b.html | 215 -- coverage/test/index-sort-f.html | 215 -- coverage/test/index-sort-l.html | 215 -- coverage/test/index.html | 215 -- coverage/updown.png | Bin 117 -> 0 bytes lcov.info | 1786 ----------------- test-foundry/L1GatewayRouter.t.sol | 100 +- 196 files changed, 66 insertions(+), 28241 deletions(-) delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func-sort-c.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.gcov.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-b.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-f.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-l.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func-sort-c.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.gcov.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-b.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-f.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-l.html delete mode 100644 coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index.html delete mode 100644 coverage/amber.png delete mode 100644 coverage/arbitrum/L2ArbitrumMessenger.sol.func-sort-c.html delete mode 100644 coverage/arbitrum/L2ArbitrumMessenger.sol.func.html delete mode 100644 coverage/arbitrum/L2ArbitrumMessenger.sol.gcov.html delete mode 100644 coverage/arbitrum/ReverseArbToken.sol.func-sort-c.html delete mode 100644 coverage/arbitrum/ReverseArbToken.sol.func.html delete mode 100644 coverage/arbitrum/ReverseArbToken.sol.gcov.html delete mode 100644 coverage/arbitrum/StandardArbERC20.sol.func-sort-c.html delete mode 100644 coverage/arbitrum/StandardArbERC20.sol.func.html delete mode 100644 coverage/arbitrum/StandardArbERC20.sol.gcov.html delete mode 100644 coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func-sort-c.html delete mode 100644 coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func.html delete mode 100644 coverage/arbitrum/gateway/L2ArbitrumGateway.sol.gcov.html delete mode 100644 coverage/arbitrum/gateway/L2CustomGateway.sol.func-sort-c.html delete mode 100644 coverage/arbitrum/gateway/L2CustomGateway.sol.func.html delete mode 100644 coverage/arbitrum/gateway/L2CustomGateway.sol.gcov.html delete mode 100644 coverage/arbitrum/gateway/L2ERC20Gateway.sol.func-sort-c.html delete mode 100644 coverage/arbitrum/gateway/L2ERC20Gateway.sol.func.html delete mode 100644 coverage/arbitrum/gateway/L2ERC20Gateway.sol.gcov.html delete mode 100644 coverage/arbitrum/gateway/L2GatewayRouter.sol.func-sort-c.html delete mode 100644 coverage/arbitrum/gateway/L2GatewayRouter.sol.func.html delete mode 100644 coverage/arbitrum/gateway/L2GatewayRouter.sol.gcov.html delete mode 100644 coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func-sort-c.html delete mode 100644 coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func.html delete mode 100644 coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.gcov.html delete mode 100644 coverage/arbitrum/gateway/L2WethGateway.sol.func-sort-c.html delete mode 100644 coverage/arbitrum/gateway/L2WethGateway.sol.func.html delete mode 100644 coverage/arbitrum/gateway/L2WethGateway.sol.gcov.html delete mode 100644 coverage/arbitrum/gateway/index-sort-b.html delete mode 100644 coverage/arbitrum/gateway/index-sort-f.html delete mode 100644 coverage/arbitrum/gateway/index-sort-l.html delete mode 100644 coverage/arbitrum/gateway/index.html delete mode 100644 coverage/arbitrum/index-sort-b.html delete mode 100644 coverage/arbitrum/index-sort-f.html delete mode 100644 coverage/arbitrum/index-sort-l.html delete mode 100644 coverage/arbitrum/index.html delete mode 100644 coverage/emerald.png delete mode 100644 coverage/ethereum/L1ArbitrumMessenger.sol.func-sort-c.html delete mode 100644 coverage/ethereum/L1ArbitrumMessenger.sol.func.html delete mode 100644 coverage/ethereum/L1ArbitrumMessenger.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func-sort-c.html delete mode 100644 coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func.html delete mode 100644 coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/L1ArbitrumGateway.sol.func-sort-c.html delete mode 100644 coverage/ethereum/gateway/L1ArbitrumGateway.sol.func.html delete mode 100644 coverage/ethereum/gateway/L1ArbitrumGateway.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/L1CustomGateway.sol.func-sort-c.html delete mode 100644 coverage/ethereum/gateway/L1CustomGateway.sol.func.html delete mode 100644 coverage/ethereum/gateway/L1CustomGateway.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/L1ERC20Gateway.sol.func-sort-c.html delete mode 100644 coverage/ethereum/gateway/L1ERC20Gateway.sol.func.html delete mode 100644 coverage/ethereum/gateway/L1ERC20Gateway.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func-sort-c.html delete mode 100644 coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func.html delete mode 100644 coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/L1GatewayRouter.sol.func-sort-c.html delete mode 100644 coverage/ethereum/gateway/L1GatewayRouter.sol.func.html delete mode 100644 coverage/ethereum/gateway/L1GatewayRouter.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func-sort-c.html delete mode 100644 coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func.html delete mode 100644 coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func-sort-c.html delete mode 100644 coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func.html delete mode 100644 coverage/ethereum/gateway/L1ReverseCustomGateway.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/L1WethGateway.sol.func-sort-c.html delete mode 100644 coverage/ethereum/gateway/L1WethGateway.sol.func.html delete mode 100644 coverage/ethereum/gateway/L1WethGateway.sol.gcov.html delete mode 100644 coverage/ethereum/gateway/index-sort-b.html delete mode 100644 coverage/ethereum/gateway/index-sort-f.html delete mode 100644 coverage/ethereum/gateway/index-sort-l.html delete mode 100644 coverage/ethereum/gateway/index.html delete mode 100644 coverage/ethereum/index-sort-b.html delete mode 100644 coverage/ethereum/index-sort-f.html delete mode 100644 coverage/ethereum/index-sort-l.html delete mode 100644 coverage/ethereum/index.html delete mode 100644 coverage/gcov.css delete mode 100644 coverage/glass.png delete mode 100644 coverage/index-sort-b.html delete mode 100644 coverage/index-sort-f.html delete mode 100644 coverage/index-sort-l.html delete mode 100644 coverage/index.html delete mode 100644 coverage/libraries/AddressAliasHelper.sol.func-sort-c.html delete mode 100644 coverage/libraries/AddressAliasHelper.sol.func.html delete mode 100644 coverage/libraries/AddressAliasHelper.sol.gcov.html delete mode 100644 coverage/libraries/BytesLib.sol.func-sort-c.html delete mode 100644 coverage/libraries/BytesLib.sol.func.html delete mode 100644 coverage/libraries/BytesLib.sol.gcov.html delete mode 100644 coverage/libraries/BytesParser.sol.func-sort-c.html delete mode 100644 coverage/libraries/BytesParser.sol.func.html delete mode 100644 coverage/libraries/BytesParser.sol.gcov.html delete mode 100644 coverage/libraries/ClonableBeaconProxy.sol.func-sort-c.html delete mode 100644 coverage/libraries/ClonableBeaconProxy.sol.func.html delete mode 100644 coverage/libraries/ClonableBeaconProxy.sol.gcov.html delete mode 100644 coverage/libraries/Cloneable.sol.func-sort-c.html delete mode 100644 coverage/libraries/Cloneable.sol.func.html delete mode 100644 coverage/libraries/Cloneable.sol.gcov.html delete mode 100644 coverage/libraries/ERC165.sol.func-sort-c.html delete mode 100644 coverage/libraries/ERC165.sol.func.html delete mode 100644 coverage/libraries/ERC165.sol.gcov.html delete mode 100644 coverage/libraries/ERC20Upgradeable.sol.func-sort-c.html delete mode 100644 coverage/libraries/ERC20Upgradeable.sol.func.html delete mode 100644 coverage/libraries/ERC20Upgradeable.sol.gcov.html delete mode 100644 coverage/libraries/L2CustomGatewayToken.sol.func-sort-c.html delete mode 100644 coverage/libraries/L2CustomGatewayToken.sol.func.html delete mode 100644 coverage/libraries/L2CustomGatewayToken.sol.gcov.html delete mode 100644 coverage/libraries/L2GatewayToken.sol.func-sort-c.html delete mode 100644 coverage/libraries/L2GatewayToken.sol.func.html delete mode 100644 coverage/libraries/L2GatewayToken.sol.gcov.html delete mode 100644 coverage/libraries/ProxyUtil.sol.func-sort-c.html delete mode 100644 coverage/libraries/ProxyUtil.sol.func.html delete mode 100644 coverage/libraries/ProxyUtil.sol.gcov.html delete mode 100644 coverage/libraries/TransferAndCallToken.sol.func-sort-c.html delete mode 100644 coverage/libraries/TransferAndCallToken.sol.func.html delete mode 100644 coverage/libraries/TransferAndCallToken.sol.gcov.html delete mode 100644 coverage/libraries/Whitelist.sol.func-sort-c.html delete mode 100644 coverage/libraries/Whitelist.sol.func.html delete mode 100644 coverage/libraries/Whitelist.sol.gcov.html delete mode 100644 coverage/libraries/aeERC20.sol.func-sort-c.html delete mode 100644 coverage/libraries/aeERC20.sol.func.html delete mode 100644 coverage/libraries/aeERC20.sol.gcov.html delete mode 100644 coverage/libraries/aeWETH.sol.func-sort-c.html delete mode 100644 coverage/libraries/aeWETH.sol.func.html delete mode 100644 coverage/libraries/aeWETH.sol.gcov.html delete mode 100644 coverage/libraries/draft-ERC20PermitUpgradeable.sol.func-sort-c.html delete mode 100644 coverage/libraries/draft-ERC20PermitUpgradeable.sol.func.html delete mode 100644 coverage/libraries/draft-ERC20PermitUpgradeable.sol.gcov.html delete mode 100644 coverage/libraries/gateway/GatewayMessageHandler.sol.func-sort-c.html delete mode 100644 coverage/libraries/gateway/GatewayMessageHandler.sol.func.html delete mode 100644 coverage/libraries/gateway/GatewayMessageHandler.sol.gcov.html delete mode 100644 coverage/libraries/gateway/GatewayRouter.sol.func-sort-c.html delete mode 100644 coverage/libraries/gateway/GatewayRouter.sol.func.html delete mode 100644 coverage/libraries/gateway/GatewayRouter.sol.gcov.html delete mode 100644 coverage/libraries/gateway/TokenGateway.sol.func-sort-c.html delete mode 100644 coverage/libraries/gateway/TokenGateway.sol.func.html delete mode 100644 coverage/libraries/gateway/TokenGateway.sol.gcov.html delete mode 100644 coverage/libraries/gateway/index-sort-b.html delete mode 100644 coverage/libraries/gateway/index-sort-f.html delete mode 100644 coverage/libraries/gateway/index-sort-l.html delete mode 100644 coverage/libraries/gateway/index.html delete mode 100644 coverage/libraries/index-sort-b.html delete mode 100644 coverage/libraries/index-sort-f.html delete mode 100644 coverage/libraries/index-sort-l.html delete mode 100644 coverage/libraries/index.html delete mode 100644 coverage/ruby.png delete mode 100644 coverage/snow.png delete mode 100644 coverage/test/AddressMappingTest.sol.func-sort-c.html delete mode 100644 coverage/test/AddressMappingTest.sol.func.html delete mode 100644 coverage/test/AddressMappingTest.sol.gcov.html delete mode 100644 coverage/test/ArbSysMock.sol.func-sort-c.html delete mode 100644 coverage/test/ArbSysMock.sol.func.html delete mode 100644 coverage/test/ArbSysMock.sol.gcov.html delete mode 100644 coverage/test/InboxMock.sol.func-sort-c.html delete mode 100644 coverage/test/InboxMock.sol.func.html delete mode 100644 coverage/test/InboxMock.sol.gcov.html delete mode 100644 coverage/test/TestArbCustomToken.sol.func-sort-c.html delete mode 100644 coverage/test/TestArbCustomToken.sol.func.html delete mode 100644 coverage/test/TestArbCustomToken.sol.gcov.html delete mode 100644 coverage/test/TestArbCustomTokenBurnFee.sol.func-sort-c.html delete mode 100644 coverage/test/TestArbCustomTokenBurnFee.sol.func.html delete mode 100644 coverage/test/TestArbCustomTokenBurnFee.sol.gcov.html delete mode 100644 coverage/test/TestBytesParser.sol.func-sort-c.html delete mode 100644 coverage/test/TestBytesParser.sol.func.html delete mode 100644 coverage/test/TestBytesParser.sol.gcov.html delete mode 100644 coverage/test/TestCustomTokenL1.sol.func-sort-c.html delete mode 100644 coverage/test/TestCustomTokenL1.sol.func.html delete mode 100644 coverage/test/TestCustomTokenL1.sol.gcov.html delete mode 100644 coverage/test/TestERC20.sol.func-sort-c.html delete mode 100644 coverage/test/TestERC20.sol.func.html delete mode 100644 coverage/test/TestERC20.sol.gcov.html delete mode 100644 coverage/test/TestPostDepositCall.sol.func-sort-c.html delete mode 100644 coverage/test/TestPostDepositCall.sol.func.html delete mode 100644 coverage/test/TestPostDepositCall.sol.gcov.html delete mode 100644 coverage/test/TestWETH9.sol.func-sort-c.html delete mode 100644 coverage/test/TestWETH9.sol.func.html delete mode 100644 coverage/test/TestWETH9.sol.gcov.html delete mode 100644 coverage/test/index-sort-b.html delete mode 100644 coverage/test/index-sort-f.html delete mode 100644 coverage/test/index-sort-l.html delete mode 100644 coverage/test/index.html delete mode 100644 coverage/updown.png delete mode 100644 lcov.info diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func-sort-c.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func-sort-c.html deleted file mode 100644 index 86e58f15f2..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func-sort-c.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - MulticallV2.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ArbMulticall2.aggregate0
ArbMulticall2.blockAndAggregate0
ArbMulticall2.getBlockHash0
ArbMulticall2.getBlockNumber0
ArbMulticall2.getCurrentBlockCoinbase0
ArbMulticall2.getCurrentBlockDifficulty0
ArbMulticall2.getCurrentBlockGasLimit0
ArbMulticall2.getCurrentBlockTimestamp0
ArbMulticall2.getEthBalance0
ArbMulticall2.getL1BlockNumber0
ArbMulticall2.getLastBlockHash0
ArbMulticall2.tryAggregate0
ArbMulticall2.tryAggregateGasRation0
ArbMulticall2.tryBlockAndAggregate0
Multicall2.aggregate0
Multicall2.blockAndAggregate0
Multicall2.getBlockHash0
Multicall2.getBlockNumber0
Multicall2.getCurrentBlockCoinbase0
Multicall2.getCurrentBlockDifficulty0
Multicall2.getCurrentBlockGasLimit0
Multicall2.getCurrentBlockTimestamp0
Multicall2.getEthBalance0
Multicall2.getLastBlockHash0
Multicall2.tryAggregate0
Multicall2.tryAggregateGasRation0
Multicall2.tryBlockAndAggregate0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func.html deleted file mode 100644 index cd0fd54d72..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.func.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - MulticallV2.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ArbMulticall2.aggregate0
ArbMulticall2.blockAndAggregate0
ArbMulticall2.getBlockHash0
ArbMulticall2.getBlockNumber0
ArbMulticall2.getCurrentBlockCoinbase0
ArbMulticall2.getCurrentBlockDifficulty0
ArbMulticall2.getCurrentBlockGasLimit0
ArbMulticall2.getCurrentBlockTimestamp0
ArbMulticall2.getEthBalance0
ArbMulticall2.getL1BlockNumber0
ArbMulticall2.getLastBlockHash0
ArbMulticall2.tryAggregate0
ArbMulticall2.tryAggregateGasRation0
ArbMulticall2.tryBlockAndAggregate0
Multicall2.aggregate0
Multicall2.blockAndAggregate0
Multicall2.getBlockHash0
Multicall2.getBlockNumber0
Multicall2.getCurrentBlockCoinbase0
Multicall2.getCurrentBlockDifficulty0
Multicall2.getCurrentBlockGasLimit0
Multicall2.getCurrentBlockTimestamp0
Multicall2.getEthBalance0
Multicall2.getLastBlockHash0
Multicall2.tryAggregate0
Multicall2.tryAggregateGasRation0
Multicall2.tryBlockAndAggregate0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.gcov.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.gcov.html deleted file mode 100644 index 1503749427..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol.gcov.html +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/MulticallV2.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - MulticallV2.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MIT
-       2                 :            : // solhint-disable-next-line compiler-version
-       3                 :            : pragma solidity >=0.5.0;
-       4                 :            : pragma experimental ABIEncoderV2;
-       5                 :            : 
-       6                 :            : import "@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol";
-       7                 :            : 
-       8                 :            : // implementation from https://github.com/makerdao/multicall/blob/1e1b44362640820bef92d0ccf5eeee25d9b41474/src/Multicall2.sol MIT License
-       9                 :            : 
-      10                 :            : /// @title Multicall2 - Aggregate results from multiple read-only function calls
-      11                 :            : /// @author Michael Elliot <mike@makerdao.com>
-      12                 :            : /// @author Joshua Levine <joshua@makerdao.com>
-      13                 :            : /// @author Nick Johnson <arachnid@notdot.net>
-      14                 :            : 
-      15                 :            : contract Multicall2 {
-      16                 :            :     struct Call {
-      17                 :            :         address target;
-      18                 :            :         bytes callData;
-      19                 :            :     }
-      20                 :            :     struct Result {
-      21                 :            :         bool success;
-      22                 :            :         bytes returnData;
-      23                 :            :     }
-      24                 :            : 
-      25                 :            :     function aggregate(Call[] memory calls)
-      26                 :            :         public
-      27                 :            :         returns (uint256 blockNumber, bytes[] memory returnData)
-      28                 :            :     {
-      29                 :          0 :         blockNumber = block.number;
-      30                 :          0 :         returnData = new bytes[](calls.length);
-      31                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
-      32                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
-      33         [ #  # ]:          0 :             require(success, "Multicall aggregate: call failed");
-      34                 :          0 :             returnData[i] = ret;
-      35                 :            :         }
-      36                 :            :     }
-      37                 :            : 
-      38                 :            :     function blockAndAggregate(Call[] memory calls)
-      39                 :            :         public
-      40                 :            :         returns (
-      41                 :            :             uint256 blockNumber,
-      42                 :            :             bytes32 blockHash,
-      43                 :            :             Result[] memory returnData
-      44                 :            :         )
-      45                 :            :     {
-      46                 :          0 :         (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
-      47                 :            :     }
-      48                 :            : 
-      49                 :            :     function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
-      50                 :          0 :         blockHash = blockhash(blockNumber);
-      51                 :            :     }
-      52                 :            : 
-      53                 :            :     function getBlockNumber() public view returns (uint256 blockNumber) {
-      54                 :          0 :         blockNumber = block.number;
-      55                 :            :     }
-      56                 :            : 
-      57                 :            :     function getCurrentBlockCoinbase() public view returns (address coinbase) {
-      58                 :          0 :         coinbase = block.coinbase;
-      59                 :            :     }
-      60                 :            : 
-      61                 :            :     function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
-      62                 :          0 :         difficulty = block.difficulty;
-      63                 :            :     }
-      64                 :            : 
-      65                 :            :     function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
-      66                 :          0 :         gaslimit = block.gaslimit;
-      67                 :            :     }
-      68                 :            : 
-      69                 :            :     function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
-      70                 :          0 :         timestamp = block.timestamp;
-      71                 :            :     }
-      72                 :            : 
-      73                 :            :     function getEthBalance(address addr) public view returns (uint256 balance) {
-      74                 :          0 :         balance = addr.balance;
-      75                 :            :     }
-      76                 :            : 
-      77                 :            :     function getLastBlockHash() public view returns (bytes32 blockHash) {
-      78                 :          0 :         blockHash = blockhash(block.number - 1);
-      79                 :            :     }
-      80                 :            : 
-      81                 :            :     function tryAggregateGasRation(bool requireSuccess, Call[] memory calls)
-      82                 :            :         public
-      83                 :            :         returns (Result[] memory returnData)
-      84                 :            :     {
-      85                 :          0 :         returnData = new Result[](calls.length);
-      86                 :          0 :         uint256 gasPerCall = gasleft() / calls.length;
-      87                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
-      88                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call{
-      89                 :            :                 gas: gasleft() > gasPerCall ? gasPerCall : gasleft()
-      90                 :            :             }(calls[i].callData);
-      91                 :            : 
-      92         [ #  # ]:          0 :             if (requireSuccess) {
-      93         [ #  # ]:          0 :                 require(success, "Multicall2 aggregate: call failed");
-      94                 :            :             }
-      95                 :            : 
-      96                 :          0 :             returnData[i] = Result(success, ret);
-      97                 :            :         }
-      98                 :            :     }
-      99                 :            : 
-     100                 :            :     function tryAggregate(bool requireSuccess, Call[] memory calls)
-     101                 :            :         public
-     102                 :            :         returns (Result[] memory returnData)
-     103                 :            :     {
-     104                 :          0 :         returnData = new Result[](calls.length);
-     105                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
-     106                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
-     107                 :            : 
-     108         [ #  # ]:          0 :             if (requireSuccess) {
-     109         [ #  # ]:          0 :                 require(success, "Multicall2 aggregate: call failed");
-     110                 :            :             }
-     111                 :            : 
-     112                 :          0 :             returnData[i] = Result(success, ret);
-     113                 :            :         }
-     114                 :            :     }
-     115                 :            : 
-     116                 :            :     function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)
-     117                 :            :         public
-     118                 :            :         returns (
-     119                 :            :             uint256 blockNumber,
-     120                 :            :             bytes32 blockHash,
-     121                 :            :             Result[] memory returnData
-     122                 :            :         )
-     123                 :            :     {
-     124                 :          0 :         blockNumber = block.number;
-     125                 :          0 :         blockHash = blockhash(block.number);
-     126                 :          0 :         returnData = tryAggregate(requireSuccess, calls);
-     127                 :            :     }
-     128                 :            : }
-     129                 :            : 
-     130                 :            : /// @title Arbitrum Multicall2 - Multicall2 contracts with L1 and L2 block numbers
-     131                 :            : contract ArbMulticall2 {
-     132                 :            :     struct Call {
-     133                 :            :         address target;
-     134                 :            :         bytes callData;
-     135                 :            :     }
-     136                 :            :     struct Result {
-     137                 :            :         bool success;
-     138                 :            :         bytes returnData;
-     139                 :            :     }
-     140                 :            : 
-     141                 :            :     function aggregate(Call[] memory calls)
-     142                 :            :         public
-     143                 :            :         returns (uint256 blockNumber, bytes[] memory returnData)
-     144                 :            :     {
-     145                 :          0 :         blockNumber = ArbSys(address(100)).arbBlockNumber();
-     146                 :          0 :         returnData = new bytes[](calls.length);
-     147                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
-     148                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
-     149         [ #  # ]:          0 :             require(success, "Multicall aggregate: call failed");
-     150                 :          0 :             returnData[i] = ret;
-     151                 :            :         }
-     152                 :            :     }
-     153                 :            : 
-     154                 :            :     function blockAndAggregate(Call[] memory calls)
-     155                 :            :         public
-     156                 :            :         returns (
-     157                 :            :             uint256 blockNumber,
-     158                 :            :             bytes32 blockHash,
-     159                 :            :             Result[] memory returnData
-     160                 :            :         )
-     161                 :            :     {
-     162                 :          0 :         (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
-     163                 :            :     }
-     164                 :            : 
-     165                 :            :     function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
-     166                 :          0 :         blockHash = blockhash(blockNumber);
-     167                 :            :     }
-     168                 :            : 
-     169                 :            :     function getBlockNumber() public view returns (uint256 blockNumber) {
-     170                 :          0 :         blockNumber = ArbSys(address(100)).arbBlockNumber();
-     171                 :            :     }
-     172                 :            : 
-     173                 :            :     function getL1BlockNumber() public view returns (uint256 l1BlockNumber) {
-     174                 :          0 :         l1BlockNumber = block.number;
-     175                 :            :     }
-     176                 :            : 
-     177                 :            :     function getCurrentBlockCoinbase() public view returns (address coinbase) {
-     178                 :          0 :         coinbase = block.coinbase;
-     179                 :            :     }
-     180                 :            : 
-     181                 :            :     function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
-     182                 :          0 :         difficulty = block.difficulty;
-     183                 :            :     }
-     184                 :            : 
-     185                 :            :     function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
-     186                 :          0 :         gaslimit = block.gaslimit;
-     187                 :            :     }
-     188                 :            : 
-     189                 :            :     function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
-     190                 :          0 :         timestamp = block.timestamp;
-     191                 :            :     }
-     192                 :            : 
-     193                 :            :     function getEthBalance(address addr) public view returns (uint256 balance) {
-     194                 :          0 :         balance = addr.balance;
-     195                 :            :     }
-     196                 :            : 
-     197                 :            :     function getLastBlockHash() public view returns (bytes32 blockHash) {
-     198                 :          0 :         blockHash = blockhash(block.number - 1);
-     199                 :            :     }
-     200                 :            : 
-     201                 :            :     function tryAggregateGasRation(bool requireSuccess, Call[] memory calls)
-     202                 :            :         public
-     203                 :            :         returns (Result[] memory returnData)
-     204                 :            :     {
-     205                 :          0 :         returnData = new Result[](calls.length);
-     206                 :          0 :         uint256 gasPerCall = gasleft() / calls.length;
-     207                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
-     208                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call{
-     209                 :            :                 gas: gasleft() > gasPerCall ? gasPerCall : gasleft()
-     210                 :            :             }(calls[i].callData);
-     211                 :            : 
-     212         [ #  # ]:          0 :             if (requireSuccess) {
-     213         [ #  # ]:          0 :                 require(success, "Multicall2 aggregate: call failed");
-     214                 :            :             }
-     215                 :            : 
-     216                 :          0 :             returnData[i] = Result(success, ret);
-     217                 :            :         }
-     218                 :            :     }
-     219                 :            : 
-     220                 :            :     function tryAggregate(bool requireSuccess, Call[] memory calls)
-     221                 :            :         public
-     222                 :            :         returns (Result[] memory returnData)
-     223                 :            :     {
-     224                 :          0 :         returnData = new Result[](calls.length);
-     225                 :          0 :         for (uint256 i = 0; i < calls.length; i++) {
-     226                 :          0 :             (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
-     227                 :            : 
-     228         [ #  # ]:          0 :             if (requireSuccess) {
-     229         [ #  # ]:          0 :                 require(success, "Multicall2 aggregate: call failed");
-     230                 :            :             }
-     231                 :            : 
-     232                 :          0 :             returnData[i] = Result(success, ret);
-     233                 :            :         }
-     234                 :            :     }
-     235                 :            : 
-     236                 :            :     function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)
-     237                 :            :         public
-     238                 :            :         returns (
-     239                 :            :             uint256 blockNumber,
-     240                 :            :             bytes32 blockHash,
-     241                 :            :             Result[] memory returnData
-     242                 :            :         )
-     243                 :            :     {
-     244                 :          0 :         blockNumber = ArbSys(address(100)).arbBlockNumber();
-     245                 :          0 :         blockHash = blockhash(block.number);
-     246                 :          0 :         returnData = tryAggregate(requireSuccess, calls);
-     247                 :            :     }
-     248                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-b.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-b.html deleted file mode 100644 index ce3442c84e..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-b.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utilsHitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MulticallV2.sol -
0.0%
-
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-f.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-f.html deleted file mode 100644 index 2d8ce65505..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-f.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utilsHitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MulticallV2.sol -
0.0%
-
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-l.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-l.html deleted file mode 100644 index 5fa664984d..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index-sort-l.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utilsHitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MulticallV2.sol -
0.0%
-
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index.html deleted file mode 100644 index a5214d9a35..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utilsHitTotalCoverage
Test:lcov.infoLines:0630.0 %
Date:2023-04-27 16:26:32Functions:0270.0 %
Branches:0200.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
MulticallV2.sol -
0.0%
-
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func-sort-c.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func-sort-c.html deleted file mode 100644 index 458f0e5fe3..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/test-foundry - L1ArbitrumExtendedGateway.t.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TestExitReceiver.onExitTransfer3072
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func.html deleted file mode 100644 index c85e01fdda..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/test-foundry - L1ArbitrumExtendedGateway.t.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TestExitReceiver.onExitTransfer3072
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.gcov.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.gcov.html deleted file mode 100644 index d97cc02661..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol.gcov.html +++ /dev/null @@ -1,408 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry/L1ArbitrumExtendedGateway.t.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - Users/goran/repos/offchain/token-bridge-contracts/test-foundry - L1ArbitrumExtendedGateway.t.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.0;
-       4                 :            : 
-       5                 :            : import "forge-std/Test.sol";
-       6                 :            : import "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol";
-       7                 :            : 
-       8                 :            : abstract contract L1ArbitrumExtendedGatewayTest is Test {
-       9                 :            :     IL1ArbitrumGateway public l1Gateway;
-      10                 :            : 
-      11                 :            :     function test_encodeWithdrawal(uint256 exitNum, address dest) public {
-      12                 :            :         bytes32 encodedWithdrawal = L1ArbitrumExtendedGateway(address(l1Gateway)).encodeWithdrawal(
-      13                 :            :             exitNum,
-      14                 :            :             dest
-      15                 :            :         );
-      16                 :            :         bytes32 expectedEncoding = keccak256(abi.encode(exitNum, dest));
-      17                 :            : 
-      18                 :            :         assertEq(encodedWithdrawal, expectedEncoding, "Invalid encodeWithdrawal");
-      19                 :            :     }
-      20                 :            : 
-      21                 :            :     function test_getExternalCall(uint256 exitNum, address dest, bytes memory data) public {
-      22                 :            :         (address target, bytes memory extData) = L1ArbitrumExtendedGateway(address(l1Gateway))
-      23                 :            :             .getExternalCall(exitNum, dest, data);
-      24                 :            : 
-      25                 :            :         assertEq(target, dest, "Invalid dest");
-      26                 :            :         assertEq(extData, data, "Invalid data");
-      27                 :            : 
-      28                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, dest));
-      29                 :            :         (bool isExit, address newTo, bytes memory newData) = L1ArbitrumExtendedGateway(
-      30                 :            :             address(l1Gateway)
-      31                 :            :         ).redirectedExits(exitId);
-      32                 :            :         assertEq(isExit, false, "Invalid isExit");
-      33                 :            :         assertEq(newTo, address(0), "Invalid _newTo");
-      34                 :            :         assertEq(newData.length, 0, "Invalid _newData");
-      35                 :            :     }
-      36                 :            : 
-      37                 :            :     function test_getExternalCall_Redirected(
-      38                 :            :         uint256 exitNum,
-      39                 :            :         address initialDest,
-      40                 :            :         address newDest,
-      41                 :            :         bytes memory data
-      42                 :            :     ) public {
-      43                 :            :         // redirect
-      44                 :            :         vm.prank(initialDest);
-      45                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-      46                 :            :             exitNum,
-      47                 :            :             initialDest,
-      48                 :            :             newDest,
-      49                 :            :             "",
-      50                 :            :             ""
-      51                 :            :         );
-      52                 :            : 
-      53                 :            :         // check getExternalCall returns new destination
-      54                 :            :         (address target, bytes memory extData) = L1ArbitrumExtendedGateway(address(l1Gateway))
-      55                 :            :             .getExternalCall(exitNum, initialDest, "");
-      56                 :            :         assertEq(target, newDest, "Invalid dest");
-      57                 :            :         assertEq(extData.length, 0, "Invalid data");
-      58                 :            : 
-      59                 :            :         // check exit redirection is properly stored
-      60                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDest));
-      61                 :            :         (bool isExit, address newTo, bytes memory newData) = L1ArbitrumExtendedGateway(
-      62                 :            :             address(l1Gateway)
-      63                 :            :         ).redirectedExits(exitId);
-      64                 :            :         assertEq(isExit, true, "Invalid isExit");
-      65                 :            :         assertEq(newTo, newDest, "Invalid _newTo");
-      66                 :            :         assertEq(newData.length, 0, "Invalid _newData");
-      67                 :            :     }
-      68                 :            : 
-      69                 :            :     function test_transferExitAndCall_EmptyData_NotRedirected(
-      70                 :            :         uint256 exitNum,
-      71                 :            :         address initialDestination,
-      72                 :            :         address newDestination
-      73                 :            :     ) public {
-      74                 :            :         bytes memory newData;
-      75                 :            :         bytes memory data;
-      76                 :            : 
-      77                 :            :         // check event
-      78                 :            :         vm.expectEmit(true, true, true, true);
-      79                 :            :         emit WithdrawRedirected(initialDestination, newDestination, exitNum, newData, data, false);
-      80                 :            : 
-      81                 :            :         // do it
-      82                 :            :         vm.prank(initialDestination);
-      83                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-      84                 :            :             exitNum,
-      85                 :            :             initialDestination,
-      86                 :            :             newDestination,
-      87                 :            :             newData,
-      88                 :            :             data
-      89                 :            :         );
-      90                 :            : 
-      91                 :            :         // check exit data is properly updated
-      92                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination));
-      93                 :            :         (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway(
-      94                 :            :             address(l1Gateway)
-      95                 :            :         ).redirectedExits(exitId);
-      96                 :            :         assertEq(isExit, true, "Invalid isExit");
-      97                 :            :         assertEq(exitTo, newDestination, "Invalid exitTo");
-      98                 :            :         assertEq(exitData.length, 0, "Invalid exitData");
-      99                 :            :     }
-     100                 :            : 
-     101                 :            :     function test_transferExitAndCall_EmptyData_Redirected(
-     102                 :            :         uint256 exitNum,
-     103                 :            :         address initialDestination
-     104                 :            :     ) public {
-     105                 :            :         bytes memory data;
-     106                 :            :         address intermediateDestination = address(new TestExitReceiver());
-     107                 :            : 
-     108                 :            :         // transfer exit
-     109                 :            :         vm.prank(initialDestination);
-     110                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     111                 :            :             exitNum,
-     112                 :            :             initialDestination,
-     113                 :            :             intermediateDestination,
-     114                 :            :             "",
-     115                 :            :             data
-     116                 :            :         );
-     117                 :            : 
-     118                 :            :         address finalDestination = address(new TestExitReceiver());
-     119                 :            :         vm.prank(intermediateDestination);
-     120                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     121                 :            :             exitNum,
-     122                 :            :             initialDestination,
-     123                 :            :             finalDestination,
-     124                 :            :             "",
-     125                 :            :             data
-     126                 :            :         );
-     127                 :            : 
-     128                 :            :         // check exit data is properly updated
-     129                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination));
-     130                 :            :         (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway(
-     131                 :            :             address(l1Gateway)
-     132                 :            :         ).redirectedExits(exitId);
-     133                 :            :         assertEq(isExit, true, "Invalid isExit");
-     134                 :            :         assertEq(exitTo, finalDestination, "Invalid exitTo");
-     135                 :            :         assertEq(exitData.length, 0, "Invalid exitData");
-     136                 :            :     }
-     137                 :            : 
-     138                 :            :     function test_transferExitAndCall_NonEmptyData(
-     139                 :            :         uint256 exitNum,
-     140                 :            :         address initialDestination
-     141                 :            :     ) public {
-     142                 :            :         bytes memory newData;
-     143                 :            :         bytes memory data = abi.encode("fun()");
-     144                 :            :         address newDestination = address(new TestExitReceiver());
-     145                 :            : 
-     146                 :            :         // check events
-     147                 :            :         vm.expectEmit(true, true, true, true);
-     148                 :            :         emit ExitHookTriggered(initialDestination, exitNum, data);
-     149                 :            : 
-     150                 :            :         vm.expectEmit(true, true, true, true);
-     151                 :            :         emit WithdrawRedirected(initialDestination, newDestination, exitNum, newData, data, true);
-     152                 :            : 
-     153                 :            :         // do it
-     154                 :            :         vm.prank(initialDestination);
-     155                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     156                 :            :             exitNum,
-     157                 :            :             initialDestination,
-     158                 :            :             newDestination,
-     159                 :            :             newData,
-     160                 :            :             data
-     161                 :            :         );
-     162                 :            : 
-     163                 :            :         // check exit data is properly updated
-     164                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination));
-     165                 :            :         (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway(
-     166                 :            :             address(l1Gateway)
-     167                 :            :         ).redirectedExits(exitId);
-     168                 :            :         assertEq(isExit, true, "Invalid isExit");
-     169                 :            :         assertEq(exitTo, newDestination, "Invalid exitTo");
-     170                 :            :         assertEq(exitData.length, 0, "Invalid exitData");
-     171                 :            :     }
-     172                 :            : 
-     173                 :            :     function test_transferExitAndCall_NonEmptyData_Redirected(
-     174                 :            :         uint256 exitNum,
-     175                 :            :         address initialDestination
-     176                 :            :     ) public {
-     177                 :            :         bytes memory data = abi.encode("run()");
-     178                 :            :         address intermediateDestination = address(new TestExitReceiver());
-     179                 :            : 
-     180                 :            :         // transfer exit
-     181                 :            :         vm.prank(initialDestination);
-     182                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     183                 :            :             exitNum,
-     184                 :            :             initialDestination,
-     185                 :            :             intermediateDestination,
-     186                 :            :             "",
-     187                 :            :             data
-     188                 :            :         );
-     189                 :            : 
-     190                 :            :         address finalDestination = address(new TestExitReceiver());
-     191                 :            :         vm.prank(intermediateDestination);
-     192                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     193                 :            :             exitNum,
-     194                 :            :             initialDestination,
-     195                 :            :             finalDestination,
-     196                 :            :             "",
-     197                 :            :             data
-     198                 :            :         );
-     199                 :            : 
-     200                 :            :         // check exit data is properly updated
-     201                 :            :         bytes32 exitId = keccak256(abi.encode(exitNum, initialDestination));
-     202                 :            :         (bool isExit, address exitTo, bytes memory exitData) = L1ArbitrumExtendedGateway(
-     203                 :            :             address(l1Gateway)
-     204                 :            :         ).redirectedExits(exitId);
-     205                 :            :         assertEq(isExit, true, "Invalid isExit");
-     206                 :            :         assertEq(exitTo, finalDestination, "Invalid exitTo");
-     207                 :            :         assertEq(exitData.length, 0, "Invalid exitData");
-     208                 :            :     }
-     209                 :            : 
-     210                 :            :     function test_transferExitAndCall_revert_NotExpectedSender() public {
-     211                 :            :         address nonSender = address(800);
-     212                 :            :         vm.expectRevert("NOT_EXPECTED_SENDER");
-     213                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     214                 :            :             4,
-     215                 :            :             nonSender,
-     216                 :            :             address(2),
-     217                 :            :             "",
-     218                 :            :             ""
-     219                 :            :         );
-     220                 :            :     }
-     221                 :            : 
-     222                 :            :     function test_transferExitAndCall_revert_NoDataAllowed() public {
-     223                 :            :         bytes memory nonEmptyData = bytes("abc");
-     224                 :            :         vm.prank(address(1));
-     225                 :            :         vm.expectRevert("NO_DATA_ALLOWED");
-     226                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     227                 :            :             4,
-     228                 :            :             address(1),
-     229                 :            :             address(2),
-     230                 :            :             nonEmptyData,
-     231                 :            :             ""
-     232                 :            :         );
-     233                 :            :     }
-     234                 :            : 
-     235                 :            :     function test_transferExitAndCall_revert_ToNotContract(address initialDestination) public {
-     236                 :            :         bytes memory data = abi.encode("execute()");
-     237                 :            :         address nonContractNewDestination = address(15);
-     238                 :            : 
-     239                 :            :         vm.prank(initialDestination);
-     240                 :            :         vm.expectRevert("TO_NOT_CONTRACT");
-     241                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     242                 :            :             4,
-     243                 :            :             initialDestination,
-     244                 :            :             nonContractNewDestination,
-     245                 :            :             "",
-     246                 :            :             data
-     247                 :            :         );
-     248                 :            :     }
-     249                 :            : 
-     250                 :            :     function test_transferExitAndCall_revert_TransferHookFail(
-     251                 :            :         uint256 exitNum,
-     252                 :            :         address initialDestination
-     253                 :            :     ) public {
-     254                 :            :         bytes memory data = abi.encode("failIt");
-     255                 :            :         address newDestination = address(new TestExitReceiver());
-     256                 :            : 
-     257                 :            :         vm.prank(initialDestination);
-     258                 :            :         vm.expectRevert("TRANSFER_HOOK_FAIL");
-     259                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     260                 :            :             exitNum,
-     261                 :            :             initialDestination,
-     262                 :            :             newDestination,
-     263                 :            :             "",
-     264                 :            :             data
-     265                 :            :         );
-     266                 :            :     }
-     267                 :            : 
-     268                 :            :     function test_transferExitAndCall_revert_TransferHookFail_Redirected(
-     269                 :            :         uint256 exitNum,
-     270                 :            :         address initialDestination
-     271                 :            :     ) public {
-     272                 :            :         bytes memory data = abi.encode("abc");
-     273                 :            :         address intermediateDestination = address(new TestExitReceiver());
-     274                 :            : 
-     275                 :            :         vm.prank(initialDestination);
-     276                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     277                 :            :             exitNum,
-     278                 :            :             initialDestination,
-     279                 :            :             intermediateDestination,
-     280                 :            :             "",
-     281                 :            :             data
-     282                 :            :         );
-     283                 :            : 
-     284                 :            :         bytes memory failData = abi.encode("failIt");
-     285                 :            :         address finalDestination = address(new TestExitReceiver());
-     286                 :            : 
-     287                 :            :         vm.prank(intermediateDestination);
-     288                 :            :         vm.expectRevert("TRANSFER_HOOK_FAIL");
-     289                 :            :         L1ArbitrumExtendedGateway(address(l1Gateway)).transferExitAndCall(
-     290                 :            :             exitNum,
-     291                 :            :             initialDestination,
-     292                 :            :             finalDestination,
-     293                 :            :             "",
-     294                 :            :             failData
-     295                 :            :         );
-     296                 :            :     }
-     297                 :            : 
-     298                 :            :     /////
-     299                 :            :     /// Event declarations
-     300                 :            :     /////
-     301                 :            :     event WithdrawRedirected(
-     302                 :            :         address indexed from,
-     303                 :            :         address indexed to,
-     304                 :            :         uint256 indexed exitNum,
-     305                 :            :         bytes newData,
-     306                 :            :         bytes data,
-     307                 :            :         bool madeExternalCall
-     308                 :            :     );
-     309                 :            :     event ExitHookTriggered(address sender, uint256 exitNum, bytes data);
-     310                 :            : }
-     311                 :            : 
-     312                 :            : contract TestExitReceiver is ITradeableExitReceiver {
-     313                 :            :     event ExitHookTriggered(address sender, uint256 exitNum, bytes data);
-     314                 :            : 
-     315                 :            :     function onExitTransfer(
-     316                 :            :         address sender,
-     317                 :            :         uint256 exitNum,
-     318                 :            :         bytes calldata data
-     319                 :            :     ) external override returns (bool) {
-     320                 :       3072 :         emit ExitHookTriggered(sender, exitNum, data);
-     321                 :       3072 :         return keccak256(data) != keccak256(abi.encode("failIt"));
-     322                 :            :     }
-     323                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-b.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-b.html deleted file mode 100644 index f569a8b36a..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-b.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/test-foundryHitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.t.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-f.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-f.html deleted file mode 100644 index a288ffe8ce..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-f.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/test-foundryHitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.t.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-l.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-l.html deleted file mode 100644 index 86c6d1f9f4..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index-sort-l.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/test-foundryHitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.t.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index.html b/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index.html deleted file mode 100644 index d203dff66d..0000000000 --- a/coverage/Users/goran/repos/offchain/token-bridge-contracts/test-foundry/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - /Users/goran/repos/offchain/token-bridge-contracts/test-foundry - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - /Users/goran/repos/offchain/token-bridge-contracts/test-foundryHitTotalCoverage
Test:lcov.infoLines:22100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.t.sol -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/amber.png b/coverage/amber.png deleted file mode 100644 index 2cab170d8359081983a4e343848dfe06bc490f12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^G2tW}LqE04T&+ z;1OBOz`!j8!i<;h*8KqrvZOouIx;Y9?C1WI$O`1M1^9%x{(levWG - - - - - - LCOV - lcov.info - arbitrum/L2ArbitrumMessenger.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum - L2ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2ArbitrumMessenger.sendTxToL10
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/L2ArbitrumMessenger.sol.func.html b/coverage/arbitrum/L2ArbitrumMessenger.sol.func.html deleted file mode 100644 index 93a5b96bec..0000000000 --- a/coverage/arbitrum/L2ArbitrumMessenger.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/L2ArbitrumMessenger.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum - L2ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2ArbitrumMessenger.sendTxToL10
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/L2ArbitrumMessenger.sol.gcov.html b/coverage/arbitrum/L2ArbitrumMessenger.sol.gcov.html deleted file mode 100644 index 7741c7522d..0000000000 --- a/coverage/arbitrum/L2ArbitrumMessenger.sol.gcov.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/L2ArbitrumMessenger.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum - L2ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol";
-      22                 :            : 
-      23                 :            : /// @notice L2 utility contract to assist with L1 <=> L2 interactions
-      24                 :            : /// @dev this is an abstract contract instead of library so the functions can be easily overriden when testing
-      25                 :            : abstract contract L2ArbitrumMessenger {
-      26                 :            :     address internal constant ARB_SYS_ADDRESS = address(100);
-      27                 :            : 
-      28                 :            :     event TxToL1(address indexed _from, address indexed _to, uint256 indexed _id, bytes _data);
-      29                 :            : 
-      30                 :            :     function sendTxToL1(
-      31                 :            :         uint256 _l1CallValue,
-      32                 :            :         address _from,
-      33                 :            :         address _to,
-      34                 :            :         bytes memory _data
-      35                 :            :     ) internal returns (uint256) {
-      36                 :          0 :         uint256 _id = ArbSys(ARB_SYS_ADDRESS).sendTxToL1{ value: _l1CallValue }(_to, _data);
-      37                 :          0 :         emit TxToL1(_from, _to, _id, _data);
-      38                 :          0 :         return _id;
-      39                 :            :     }
-      40                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/ReverseArbToken.sol.func-sort-c.html b/coverage/arbitrum/ReverseArbToken.sol.func-sort-c.html deleted file mode 100644 index 06f50d3577..0000000000 --- a/coverage/arbitrum/ReverseArbToken.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/ReverseArbToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum - ReverseArbToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ReverseArbToken.bridgeBurn0
ReverseArbToken.bridgeMint0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/ReverseArbToken.sol.func.html b/coverage/arbitrum/ReverseArbToken.sol.func.html deleted file mode 100644 index 6bcf45ee3c..0000000000 --- a/coverage/arbitrum/ReverseArbToken.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/ReverseArbToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum - ReverseArbToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ReverseArbToken.bridgeBurn0
ReverseArbToken.bridgeMint0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/ReverseArbToken.sol.gcov.html b/coverage/arbitrum/ReverseArbToken.sol.gcov.html deleted file mode 100644 index 041bc21e2b..0000000000 --- a/coverage/arbitrum/ReverseArbToken.sol.gcov.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/ReverseArbToken.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum - ReverseArbToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : // solhint-disable-next-line compiler-version
-      20                 :            : pragma solidity >=0.6.9 <0.9.0;
-      21                 :            : 
-      22                 :            : import "./IArbToken.sol";
-      23                 :            : 
-      24                 :            : /// @title  Minimum expected interface for L2 token that interacts with the reverse L2 token bridge (this is the interface necessary
-      25                 :            : ///         for a custom token that interacts with the reverse gateway, see TestArbCustomToken.sol for an example implementation).
-      26                 :            : /// @dev    The L2ArbitrumGateway expects objects of type IArbToken, which includes
-      27                 :            : ///         bridgeMint/burn. However when the L2ReverseCustomGateway overrides the functions
-      28                 :            : ///         that make use of bridgeMint/burn and replaces them with safeTransfer/from.
-      29                 :            : ///         We inherit IArbToken so that we fulfil the interface L2ArbitrumGateway expects
-      30                 :            : ///         but since we know that bridgeMint/burn won't/shouldn't be used we override these
-      31                 :            : ///         functions to ensure that if they throw if called during development
-      32                 :            : abstract contract ReverseArbToken is IArbToken {
-      33                 :            :     function bridgeMint(address, uint256) public override {
-      34                 :          0 :         revert("BRIDGE_MINT_NOT_IMPLEMENTED");
-      35                 :            :     }
-      36                 :            : 
-      37                 :            :     function bridgeBurn(address, uint256) public override {
-      38                 :          0 :         revert("BRIDGE_BURN_NOT_IMPLEMENTED");
-      39                 :            :     }
-      40                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/StandardArbERC20.sol.func-sort-c.html b/coverage/arbitrum/StandardArbERC20.sol.func-sort-c.html deleted file mode 100644 index c006309896..0000000000 --- a/coverage/arbitrum/StandardArbERC20.sol.func-sort-c.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/StandardArbERC20.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum - StandardArbERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
StandardArbERC20.bridgeInit0
StandardArbERC20.decimals0
StandardArbERC20.name0
StandardArbERC20.symbol0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/StandardArbERC20.sol.func.html b/coverage/arbitrum/StandardArbERC20.sol.func.html deleted file mode 100644 index ae8ab8bd34..0000000000 --- a/coverage/arbitrum/StandardArbERC20.sol.func.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/StandardArbERC20.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum - StandardArbERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
StandardArbERC20.bridgeInit0
StandardArbERC20.decimals0
StandardArbERC20.name0
StandardArbERC20.symbol0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/StandardArbERC20.sol.gcov.html b/coverage/arbitrum/StandardArbERC20.sol.gcov.html deleted file mode 100644 index c3ca0b1f33..0000000000 --- a/coverage/arbitrum/StandardArbERC20.sol.gcov.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/StandardArbERC20.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum - StandardArbERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:060.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../libraries/Cloneable.sol";
-      22                 :            : import "../libraries/L2GatewayToken.sol";
-      23                 :            : import "../libraries/BytesParser.sol";
-      24                 :            : import "./IArbToken.sol";
-      25                 :            : 
-      26                 :            : /**
-      27                 :            :  * @title Standard (i.e., non-custom) contract deployed by L2Gateway.sol as L2 ERC20. Includes standard ERC20 interface plus additional methods for deposits/withdraws
-      28                 :            :  */
-      29                 :            : contract StandardArbERC20 is IArbToken, L2GatewayToken, Cloneable {
-      30                 :            :     struct ERC20Getters {
-      31                 :            :         bool ignoreDecimals;
-      32                 :            :         bool ignoreName;
-      33                 :            :         bool ignoreSymbol;
-      34                 :            :     }
-      35                 :            :     ERC20Getters private availableGetters;
-      36                 :            : 
-      37                 :            :     /**
-      38                 :            :      * @notice initialize the token
-      39                 :            :      * @dev the L2 bridge assumes this does not fail or revert
-      40                 :            :      * @param _l1Address L1 address of ERC20
-      41                 :            :      * @param _data encoded symbol/name/decimal data for initial deploy
-      42                 :            :      */
-      43                 :            :     function bridgeInit(address _l1Address, bytes memory _data) public virtual {
-      44                 :          0 :         (bytes memory name_, bytes memory symbol_, bytes memory decimals_) = abi.decode(
-      45                 :            :             _data,
-      46                 :            :             (bytes, bytes, bytes)
-      47                 :            :         );
-      48                 :            :         // what if decode reverts? shouldn't as this is encoded by L1 contract
-      49                 :            : 
-      50                 :            :         /*
-      51                 :            :          *  if parsing fails, the type's default value gets assigned
-      52                 :            :          *  the parsing can fail for different reasons:
-      53                 :            :          *      1. method not available in L1 (empty input)
-      54                 :            :          *      2. data type is encoded differently in the L1 (trying to abi decode the wrong data type)
-      55                 :            :          *  currently (1) returns a parser fails and (2) reverts as there is no `abi.tryDecode`
-      56                 :            :          *  https://github.com/ethereum/solidity/issues/10381
-      57                 :            :          */
-      58                 :            : 
-      59                 :          0 :         (bool parseNameSuccess, string memory parsedName) = BytesParser.toString(name_);
-      60                 :          0 :         (bool parseSymbolSuccess, string memory parsedSymbol) = BytesParser.toString(symbol_);
-      61                 :          0 :         (bool parseDecimalSuccess, uint8 parsedDecimals) = BytesParser.toUint8(decimals_);
-      62                 :            : 
-      63                 :          0 :         L2GatewayToken._initialize(
-      64                 :            :             parsedName,
-      65                 :            :             parsedSymbol,
-      66                 :            :             parsedDecimals,
-      67                 :            :             msg.sender, // _l2Gateway,
-      68                 :            :             _l1Address // _l1Counterpart
-      69                 :            :         );
-      70                 :            : 
-      71                 :            :         // here we assume that (2) would have reverted, so if the parser failed its because the getter isn't available in the L1.
-      72                 :            :         // instead of storing on a struct, we could instead set a magic number, at something like `type(uint8).max` or random string
-      73                 :            :         // to be more general we instead use an extra storage slot
-      74                 :          0 :         availableGetters = ERC20Getters({
-      75                 :            :             ignoreName: !parseNameSuccess,
-      76                 :            :             ignoreSymbol: !parseSymbolSuccess,
-      77                 :            :             ignoreDecimals: !parseDecimalSuccess
-      78                 :            :         });
-      79                 :            :     }
-      80                 :            : 
-      81                 :            :     function decimals() public view override returns (uint8) {
-      82                 :            :         // no revert message just as in the L1 if you called and the function is not implemented
-      83         [ #  # ]:          0 :         if (availableGetters.ignoreDecimals) revert();
-      84                 :          0 :         return super.decimals();
-      85                 :            :     }
-      86                 :            : 
-      87                 :            :     function name() public view override returns (string memory) {
-      88                 :            :         // no revert message just as in the L1 if you called and the function is not implemented
-      89         [ #  # ]:          0 :         if (availableGetters.ignoreName) revert();
-      90                 :          0 :         return super.name();
-      91                 :            :     }
-      92                 :            : 
-      93                 :            :     function symbol() public view override returns (string memory) {
-      94                 :            :         // no revert message just as in the L1 if you called and the function is not implemented
-      95         [ #  # ]:          0 :         if (availableGetters.ignoreSymbol) revert();
-      96                 :          0 :         return super.symbol();
-      97                 :            :     }
-      98                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func-sort-c.html deleted file mode 100644 index d0f6076984..0000000000 --- a/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func-sort-c.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2ArbitrumGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0510.0 %
Date:2023-04-27 16:26:32Functions:090.0 %
Branches:0260.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2ArbitrumGateway._initialize0
L2ArbitrumGateway.createOutboundTx0
L2ArbitrumGateway.finalizeInboundTransfer0
L2ArbitrumGateway.getOutboundCalldata0
L2ArbitrumGateway.inboundEscrowTransfer0
L2ArbitrumGateway.outboundEscrowTransfer0
L2ArbitrumGateway.outboundTransfer0
L2ArbitrumGateway.postUpgradeInit0
L2ArbitrumGateway.triggerWithdrawal0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func.html b/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func.html deleted file mode 100644 index 974962a754..0000000000 --- a/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.func.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2ArbitrumGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0510.0 %
Date:2023-04-27 16:26:32Functions:090.0 %
Branches:0260.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2ArbitrumGateway._initialize0
L2ArbitrumGateway.createOutboundTx0
L2ArbitrumGateway.finalizeInboundTransfer0
L2ArbitrumGateway.getOutboundCalldata0
L2ArbitrumGateway.inboundEscrowTransfer0
L2ArbitrumGateway.outboundEscrowTransfer0
L2ArbitrumGateway.outboundTransfer0
L2ArbitrumGateway.postUpgradeInit0
L2ArbitrumGateway.triggerWithdrawal0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.gcov.html b/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.gcov.html deleted file mode 100644 index b32e5cf757..0000000000 --- a/coverage/arbitrum/gateway/L2ArbitrumGateway.sol.gcov.html +++ /dev/null @@ -1,384 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2ArbitrumGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0510.0 %
Date:2023-04-27 16:26:32Functions:090.0 %
Branches:0260.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "@openzeppelin/contracts/utils/Address.sol";
-      22                 :            : import "../../libraries/AddressAliasHelper.sol";
-      23                 :            : import "../../libraries/BytesLib.sol";
-      24                 :            : import "../../libraries/ProxyUtil.sol";
-      25                 :            : 
-      26                 :            : import "../IArbToken.sol";
-      27                 :            : 
-      28                 :            : import "../L2ArbitrumMessenger.sol";
-      29                 :            : import "../../libraries/gateway/GatewayMessageHandler.sol";
-      30                 :            : import "../../libraries/gateway/TokenGateway.sol";
-      31                 :            : 
-      32                 :            : /**
-      33                 :            :  * @title Common interface for gatways on Arbitrum messaging to L1.
-      34                 :            :  */
-      35                 :            : abstract contract L2ArbitrumGateway is L2ArbitrumMessenger, TokenGateway {
-      36                 :            :     using Address for address;
-      37                 :            : 
-      38                 :            :     uint256 public exitNum;
-      39                 :            : 
-      40                 :            :     event DepositFinalized(
-      41                 :            :         address indexed l1Token,
-      42                 :            :         address indexed _from,
-      43                 :            :         address indexed _to,
-      44                 :            :         uint256 _amount
-      45                 :            :     );
-      46                 :            : 
-      47                 :            :     event WithdrawalInitiated(
-      48                 :            :         address l1Token,
-      49                 :            :         address indexed _from,
-      50                 :            :         address indexed _to,
-      51                 :            :         uint256 indexed _l2ToL1Id,
-      52                 :            :         uint256 _exitNum,
-      53                 :            :         uint256 _amount
-      54                 :            :     );
-      55                 :            : 
-      56                 :            :     modifier onlyCounterpartGateway() override {
-      57                 :            :         require(
-      58                 :            :             msg.sender == AddressAliasHelper.applyL1ToL2Alias(counterpartGateway),
-      59                 :            :             "ONLY_COUNTERPART_GATEWAY"
-      60                 :            :         );
-      61                 :            :         _;
-      62                 :            :     }
-      63                 :            : 
-      64                 :            :     function postUpgradeInit() external {
-      65                 :            :         // it is assumed the L2 Arbitrum Gateway contract is behind a Proxy controlled by a proxy admin
-      66                 :            :         // this function can only be called by the proxy admin contract
-      67                 :          0 :         address proxyAdmin = ProxyUtil.getProxyAdmin();
-      68         [ #  # ]:          0 :         require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");
-      69                 :            :         // this has no other logic since the current upgrade doesn't require this logic
-      70                 :            :     }
-      71                 :            : 
-      72                 :            :     function _initialize(address _l1Counterpart, address _router) internal override {
-      73                 :          0 :         TokenGateway._initialize(_l1Counterpart, _router);
-      74                 :            :         // L1 gateway must have a router
-      75         [ #  # ]:          0 :         require(_router != address(0), "BAD_ROUTER");
-      76                 :            :     }
-      77                 :            : 
-      78                 :            :     function createOutboundTx(
-      79                 :            :         address _from,
-      80                 :            :         uint256, /* _tokenAmount */
-      81                 :            :         bytes memory _outboundCalldata
-      82                 :            :     ) internal virtual returns (uint256) {
-      83                 :            :         // We make this function virtual since outboundTransfer logic is the same for many gateways
-      84                 :            :         // but sometimes (ie weth) you construct the outgoing message differently.
-      85                 :            : 
-      86                 :            :         // exitNum incremented after being included in _outboundCalldata
-      87                 :          0 :         exitNum++;
-      88                 :          0 :         return
-      89                 :            :             sendTxToL1(
-      90                 :            :                 // default to sending no callvalue to the L1
-      91                 :            :                 0,
-      92                 :            :                 _from,
-      93                 :            :                 counterpartGateway,
-      94                 :            :                 _outboundCalldata
-      95                 :            :             );
-      96                 :            :     }
-      97                 :            : 
-      98                 :            :     function getOutboundCalldata(
-      99                 :            :         address _token,
-     100                 :            :         address _from,
-     101                 :            :         address _to,
-     102                 :            :         uint256 _amount,
-     103                 :            :         bytes memory _data
-     104                 :            :     ) public view override returns (bytes memory outboundCalldata) {
-     105                 :          0 :         outboundCalldata = abi.encodeWithSelector(
-     106                 :            :             ITokenGateway.finalizeInboundTransfer.selector,
-     107                 :            :             _token,
-     108                 :            :             _from,
-     109                 :            :             _to,
-     110                 :            :             _amount,
-     111                 :            :             GatewayMessageHandler.encodeFromL2GatewayMsg(exitNum, _data)
-     112                 :            :         );
-     113                 :            : 
-     114                 :          0 :         return outboundCalldata;
-     115                 :            :     }
-     116                 :            : 
-     117                 :            :     function outboundTransfer(
-     118                 :            :         address _l1Token,
-     119                 :            :         address _to,
-     120                 :            :         uint256 _amount,
-     121                 :            :         bytes calldata _data
-     122                 :            :     ) public payable returns (bytes memory) {
-     123                 :          0 :         return outboundTransfer(_l1Token, _to, _amount, 0, 0, _data);
-     124                 :            :     }
-     125                 :            : 
-     126                 :            :     /**
-     127                 :            :      * @notice Initiates a token withdrawal from Arbitrum to Ethereum
-     128                 :            :      * @param _l1Token l1 address of token
-     129                 :            :      * @param _to destination address
-     130                 :            :      * @param _amount amount of tokens withdrawn
-     131                 :            :      * @return res encoded unique identifier for withdrawal
-     132                 :            :      */
-     133                 :            :     function outboundTransfer(
-     134                 :            :         address _l1Token,
-     135                 :            :         address _to,
-     136                 :            :         uint256 _amount,
-     137                 :            :         uint256, /* _maxGas */
-     138                 :            :         uint256, /* _gasPriceBid */
-     139                 :            :         bytes calldata _data
-     140                 :            :     ) public payable override returns (bytes memory res) {
-     141                 :            :         // This function is set as public and virtual so that subclasses can override
-     142                 :            :         // it and add custom validation for callers (ie only whitelisted users)
-     143                 :            : 
-     144                 :            :         // the function is marked as payable to conform to the inheritance setup
-     145                 :            :         // this particular code path shouldn't have a msg.value > 0
-     146                 :            :         // TODO: remove this invariant for execution markets
-     147         [ #  # ]:          0 :         require(msg.value == 0, "NO_VALUE");
-     148                 :            : 
-     149                 :          0 :         address _from;
-     150                 :          0 :         bytes memory _extraData;
-     151                 :            :         {
-     152         [ #  # ]:          0 :             if (isRouter(msg.sender)) {
-     153                 :          0 :                 (_from, _extraData) = GatewayMessageHandler.parseFromRouterToGateway(_data);
-     154                 :            :             } else {
-     155                 :          0 :                 _from = msg.sender;
-     156                 :          0 :                 _extraData = _data;
-     157                 :            :             }
-     158                 :            :         }
-     159                 :            :         // the inboundEscrowAndCall functionality has been disabled, so no data is allowed
-     160         [ #  # ]:          0 :         require(_extraData.length == 0, "EXTRA_DATA_DISABLED");
-     161                 :            : 
-     162                 :          0 :         uint256 id;
-     163                 :            :         {
-     164                 :          0 :             address l2Token = calculateL2TokenAddress(_l1Token);
-     165         [ #  # ]:          0 :             require(l2Token.isContract(), "TOKEN_NOT_DEPLOYED");
-     166         [ #  # ]:          0 :             require(IArbToken(l2Token).l1Address() == _l1Token, "NOT_EXPECTED_L1_TOKEN");
-     167                 :            : 
-     168                 :          0 :             _amount = outboundEscrowTransfer(l2Token, _from, _amount);
-     169                 :          0 :             id = triggerWithdrawal(_l1Token, _from, _to, _amount, _extraData);
-     170                 :            :         }
-     171                 :          0 :         return abi.encode(id);
-     172                 :            :     }
-     173                 :            : 
-     174                 :            :     function triggerWithdrawal(
-     175                 :            :         address _l1Token,
-     176                 :            :         address _from,
-     177                 :            :         address _to,
-     178                 :            :         uint256 _amount,
-     179                 :            :         bytes memory _data
-     180                 :            :     ) internal returns (uint256) {
-     181                 :            :         // exit number used for tradeable exits
-     182                 :          0 :         uint256 currExitNum = exitNum;
-     183                 :            :         // unique id used to identify the L2 to L1 tx
-     184                 :          0 :         uint256 id = createOutboundTx(
-     185                 :            :             _from,
-     186                 :            :             _amount,
-     187                 :            :             getOutboundCalldata(_l1Token, _from, _to, _amount, _data)
-     188                 :            :         );
-     189                 :          0 :         emit WithdrawalInitiated(_l1Token, _from, _to, id, currExitNum, _amount);
-     190                 :          0 :         return id;
-     191                 :            :     }
-     192                 :            : 
-     193                 :            :     function outboundEscrowTransfer(
-     194                 :            :         address _l2Token,
-     195                 :            :         address _from,
-     196                 :            :         uint256 _amount
-     197                 :            :     ) internal virtual returns (uint256 amountBurnt) {
-     198                 :            :         // this method is virtual since different subclasses can handle escrow differently
-     199                 :            :         // user funds are escrowed on the gateway using this function
-     200                 :            :         // burns L2 tokens in order to release escrowed L1 tokens
-     201                 :          0 :         IArbToken(_l2Token).bridgeBurn(_from, _amount);
-     202                 :            :         // by default we assume that the amount we send to bridgeBurn is the amount burnt
-     203                 :            :         // this might not be the case for every token
-     204                 :          0 :         return _amount;
-     205                 :            :     }
-     206                 :            : 
-     207                 :            :     function inboundEscrowTransfer(
-     208                 :            :         address _l2Address,
-     209                 :            :         address _dest,
-     210                 :            :         uint256 _amount
-     211                 :            :     ) internal virtual {
-     212                 :            :         // this method is virtual since different subclasses can handle escrow differently
-     213                 :          0 :         IArbToken(_l2Address).bridgeMint(_dest, _amount);
-     214                 :            :     }
-     215                 :            : 
-     216                 :            :     /**
-     217                 :            :      * @notice Mint on L2 upon L1 deposit.
-     218                 :            :      * If token not yet deployed and symbol/name/decimal data is included, deploys StandardArbERC20
-     219                 :            :      * @dev Callable only by the L1ERC20Gateway.outboundTransfer method. For initial deployments of a token the L1 L1ERC20Gateway
-     220                 :            :      * is expected to include the deployData. If not a L1 withdrawal is automatically triggered for the user
-     221                 :            :      * @param _token L1 address of ERC20
-     222                 :            :      * @param _from account that initiated the deposit in the L1
-     223                 :            :      * @param _to account to be credited with the tokens in the L2 (can be the user's L2 account or a contract)
-     224                 :            :      * @param _amount token amount to be minted to the user
-     225                 :            :      * @param _data encoded symbol/name/decimal data for deploy, in addition to any additional callhook data
-     226                 :            :      */
-     227                 :            :     function finalizeInboundTransfer(
-     228                 :            :         address _token,
-     229                 :            :         address _from,
-     230                 :            :         address _to,
-     231                 :            :         uint256 _amount,
-     232                 :            :         bytes calldata _data
-     233                 :            :     ) external payable override onlyCounterpartGateway {
-     234                 :          0 :         (bytes memory gatewayData, bytes memory callHookData) = GatewayMessageHandler
-     235                 :            :             .parseFromL1GatewayMsg(_data);
-     236                 :            : 
-     237         [ #  # ]:          0 :         if (callHookData.length != 0) {
-     238                 :            :             // callHookData should always be 0 since inboundEscrowAndCall is disabled
-     239                 :          0 :             callHookData = bytes("");
-     240                 :            :         }
-     241                 :            : 
-     242                 :          0 :         address expectedAddress = calculateL2TokenAddress(_token);
-     243                 :            : 
-     244         [ #  # ]:          0 :         if (!expectedAddress.isContract()) {
-     245                 :          0 :             bool shouldHalt = handleNoContract(
-     246                 :            :                 _token,
-     247                 :            :                 expectedAddress,
-     248                 :            :                 _from,
-     249                 :            :                 _to,
-     250                 :            :                 _amount,
-     251                 :            :                 gatewayData
-     252                 :            :             );
-     253         [ #  # ]:          0 :             if (shouldHalt) return;
-     254                 :            :         }
-     255                 :            :         // ignores gatewayData if token already deployed
-     256                 :            : 
-     257                 :            :         {
-     258                 :            :             // validate if L1 address supplied matches that of the expected L2 address
-     259                 :          0 :             (bool success, bytes memory _l1AddressData) = expectedAddress.staticcall(
-     260                 :            :                 abi.encodeWithSelector(IArbToken.l1Address.selector)
-     261                 :            :             );
-     262                 :            : 
-     263                 :          0 :             bool shouldWithdraw;
-     264         [ #  # ]:          0 :             if (!success || _l1AddressData.length < 32) {
-     265                 :          0 :                 shouldWithdraw = true;
-     266                 :            :             } else {
-     267                 :            :                 // we do this in the else branch since we want to avoid reverts
-     268                 :            :                 // and `toAddress` reverts if _l1AddressData has a short length
-     269                 :            :                 // `_l1AddressData` should be 12 bytes of padding then 20 bytes for the address
-     270                 :          0 :                 address expectedL1Address = BytesLib.toAddress(_l1AddressData, 12);
-     271         [ #  # ]:          0 :                 if (expectedL1Address != _token) {
-     272                 :          0 :                     shouldWithdraw = true;
-     273                 :            :                 }
-     274                 :            :             }
-     275                 :            : 
-     276         [ #  # ]:          0 :             if (shouldWithdraw) {
-     277                 :            :                 // we don't need the return value from triggerWithdrawal since this is forcing
-     278                 :            :                 // a withdrawal back to the L1 instead of composing with a L2 dapp
-     279                 :          0 :                 triggerWithdrawal(_token, address(this), _from, _amount, "");
-     280                 :          0 :                 return;
-     281                 :            :             }
-     282                 :            :         }
-     283                 :            : 
-     284                 :          0 :         inboundEscrowTransfer(expectedAddress, _to, _amount);
-     285                 :          0 :         emit DepositFinalized(_token, _from, _to, _amount);
-     286                 :            : 
-     287                 :          0 :         return;
-     288                 :            :     }
-     289                 :            : 
-     290                 :            :     // returns if function should halt after
-     291                 :            :     function handleNoContract(
-     292                 :            :         address _l1Token,
-     293                 :            :         address expectedL2Address,
-     294                 :            :         address _from,
-     295                 :            :         address _to,
-     296                 :            :         uint256 _amount,
-     297                 :            :         bytes memory gatewayData
-     298                 :            :     ) internal virtual returns (bool shouldHalt);
-     299                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2CustomGateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2CustomGateway.sol.func-sort-c.html deleted file mode 100644 index 00771b24f5..0000000000 --- a/coverage/arbitrum/gateway/L2CustomGateway.sol.func-sort-c.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2CustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2CustomGateway.calculateL2TokenAddress0
L2CustomGateway.handleNoContract0
L2CustomGateway.initialize0
L2CustomGateway.registerTokenFromL10
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2CustomGateway.sol.func.html b/coverage/arbitrum/gateway/L2CustomGateway.sol.func.html deleted file mode 100644 index 7f67274113..0000000000 --- a/coverage/arbitrum/gateway/L2CustomGateway.sol.func.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2CustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2CustomGateway.calculateL2TokenAddress0
L2CustomGateway.handleNoContract0
L2CustomGateway.initialize0
L2CustomGateway.registerTokenFromL10
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2CustomGateway.sol.gcov.html b/coverage/arbitrum/gateway/L2CustomGateway.sol.gcov.html deleted file mode 100644 index 67e20c44c9..0000000000 --- a/coverage/arbitrum/gateway/L2CustomGateway.sol.gcov.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2CustomGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./L2ArbitrumGateway.sol";
-      22                 :            : import "../../libraries/gateway/ICustomGateway.sol";
-      23                 :            : import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
-      24                 :            : 
-      25                 :            : contract L2CustomGateway is L2ArbitrumGateway, ICustomGateway {
-      26                 :            :     // stores addresses of L2 tokens to be used
-      27                 :            :     mapping(address => address) public override l1ToL2Token;
-      28                 :            : 
-      29                 :            :     function initialize(address _l1Counterpart, address _router) public {
-      30                 :          0 :         L2ArbitrumGateway._initialize(_l1Counterpart, _router);
-      31                 :            :     }
-      32                 :            : 
-      33                 :            :     /**
-      34                 :            :      * @notice internal utility function used to handle when no contract is deployed at expected address
-      35                 :            :      */
-      36                 :            :     function handleNoContract(
-      37                 :            :         address _l1Token,
-      38                 :            :         address, /* expectedL2Address */
-      39                 :            :         address _from,
-      40                 :            :         address, /* _to */
-      41                 :            :         uint256 _amount,
-      42                 :            :         bytes memory /* gatewayData */
-      43                 :            :     ) internal override returns (bool shouldHalt) {
-      44                 :            :         // it is assumed that the custom token is deployed in the L2 before deposits are made
-      45                 :            :         // trigger withdrawal
-      46                 :            :         // we don't need the return value from triggerWithdrawal since this is forcing a withdrawal back to the L1
-      47                 :            :         // instead of composing with a L2 dapp
-      48                 :          0 :         triggerWithdrawal(_l1Token, address(this), _from, _amount, "");
-      49                 :          0 :         return true;
-      50                 :            :     }
-      51                 :            : 
-      52                 :            :     /**
-      53                 :            :      * @notice Calculate the address used when bridging an ERC20 token
-      54                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
-      55                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
-      56                 :            :      * @param l1ERC20 address of L1 token
-      57                 :            :      * @return L2 address of a bridged ERC20 token
-      58                 :            :      */
-      59                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override returns (address) {
-      60                 :          0 :         return l1ToL2Token[l1ERC20];
-      61                 :            :     }
-      62                 :            : 
-      63                 :            :     function registerTokenFromL1(address[] calldata l1Address, address[] calldata l2Address)
-      64                 :            :         external
-      65                 :            :         onlyCounterpartGateway
-      66                 :            :     {
-      67                 :            :         // we assume both arrays are the same length, safe since its encoded by the L1
-      68                 :          0 :         for (uint256 i = 0; i < l1Address.length; i++) {
-      69                 :            :             // here we don't check if l2Address is a contract and instead deal with that behaviour
-      70                 :            :             // in `handleNoContract` this way we keep the l1 and l2 address oracles in sync
-      71                 :          0 :             l1ToL2Token[l1Address[i]] = l2Address[i];
-      72                 :          0 :             emit TokenSet(l1Address[i], l2Address[i]);
-      73                 :            :         }
-      74                 :            :     }
-      75                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func-sort-c.html deleted file mode 100644 index 3b38504879..0000000000 --- a/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func-sort-c.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2ERC20Gateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0130.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2ERC20Gateway.calculateL2TokenAddress0
L2ERC20Gateway.cloneableProxyHash0
L2ERC20Gateway.getUserSalt0
L2ERC20Gateway.handleNoContract0
L2ERC20Gateway.initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func.html b/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func.html deleted file mode 100644 index c6bdd67336..0000000000 --- a/coverage/arbitrum/gateway/L2ERC20Gateway.sol.func.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2ERC20Gateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0130.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2ERC20Gateway.calculateL2TokenAddress0
L2ERC20Gateway.cloneableProxyHash0
L2ERC20Gateway.getUserSalt0
L2ERC20Gateway.handleNoContract0
L2ERC20Gateway.initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2ERC20Gateway.sol.gcov.html b/coverage/arbitrum/gateway/L2ERC20Gateway.sol.gcov.html deleted file mode 100644 index 9921d03c9b..0000000000 --- a/coverage/arbitrum/gateway/L2ERC20Gateway.sol.gcov.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2ERC20Gateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0130.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:040.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
-      22                 :            : import "@openzeppelin/contracts/utils/Create2.sol";
-      23                 :            : import "./L2ArbitrumGateway.sol";
-      24                 :            : import "../StandardArbERC20.sol";
-      25                 :            : import "../../libraries/ClonableBeaconProxy.sol";
-      26                 :            : 
-      27                 :            : contract L2ERC20Gateway is L2ArbitrumGateway {
-      28                 :            :     address public beaconProxyFactory;
-      29                 :            : 
-      30                 :            :     function initialize(
-      31                 :            :         address _l1Counterpart,
-      32                 :            :         address _router,
-      33                 :            :         address _beaconProxyFactory
-      34                 :            :     ) public {
-      35                 :          0 :         L2ArbitrumGateway._initialize(_l1Counterpart, _router);
-      36         [ #  # ]:          0 :         require(_beaconProxyFactory != address(0), "INVALID_BEACON");
-      37                 :          0 :         beaconProxyFactory = _beaconProxyFactory;
-      38                 :            :     }
-      39                 :            : 
-      40                 :            :     /**
-      41                 :            :      * @notice Calculate the address used when bridging an ERC20 token
-      42                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
-      43                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
-      44                 :            :      * @param l1ERC20 address of L1 token
-      45                 :            :      * @return L2 address of a bridged ERC20 token
-      46                 :            :      */
-      47                 :            :     function calculateL2TokenAddress(address l1ERC20)
-      48                 :            :         public
-      49                 :            :         view
-      50                 :            :         virtual
-      51                 :            :         override
-      52                 :            :         returns (address)
-      53                 :            :     {
-      54                 :            :         // this method is marked virtual to be overriden in subclasses used in testing
-      55                 :          0 :         return
-      56                 :            :             BeaconProxyFactory(beaconProxyFactory).calculateExpectedAddress(
-      57                 :            :                 address(this),
-      58                 :            :                 getUserSalt(l1ERC20)
-      59                 :            :             );
-      60                 :            :     }
-      61                 :            : 
-      62                 :            :     function cloneableProxyHash() public view returns (bytes32) {
-      63                 :          0 :         return BeaconProxyFactory(beaconProxyFactory).cloneableProxyHash();
-      64                 :            :     }
-      65                 :            : 
-      66                 :            :     function getUserSalt(address l1ERC20) public pure returns (bytes32) {
-      67                 :          0 :         return keccak256(abi.encode(l1ERC20));
-      68                 :            :     }
-      69                 :            : 
-      70                 :            :     /**
-      71                 :            :      * @notice internal utility function used to deploy ERC20 tokens with the beacon proxy pattern.
-      72                 :            :      * @dev the transparent proxy implementation by OpenZeppelin can't be used if we want to be able to
-      73                 :            :      * upgrade the token logic.
-      74                 :            :      * @param l1ERC20 L1 address of ERC20
-      75                 :            :      * @param expectedL2Address L2 address of ERC20
-      76                 :            :      * @param deployData encoded symbol/name/decimal data for initial deploy
-      77                 :            :      */
-      78                 :            :     function handleNoContract(
-      79                 :            :         address l1ERC20,
-      80                 :            :         address expectedL2Address,
-      81                 :            :         address _from,
-      82                 :            :         address, /* _to */
-      83                 :            :         uint256 _amount,
-      84                 :            :         bytes memory deployData
-      85                 :            :     ) internal override returns (bool shouldHalt) {
-      86                 :          0 :         bytes32 userSalt = getUserSalt(l1ERC20);
-      87                 :          0 :         address createdContract = BeaconProxyFactory(beaconProxyFactory).createProxy(userSalt);
-      88                 :            : 
-      89                 :          0 :         StandardArbERC20(createdContract).bridgeInit(l1ERC20, deployData);
-      90                 :            : 
-      91         [ #  # ]:          0 :         if (createdContract == expectedL2Address) {
-      92                 :          0 :             return false;
-      93                 :            :         } else {
-      94                 :            :             // trigger withdrawal then halt
-      95                 :            :             // this codepath should only be hit if the system is setup incorrectly
-      96                 :            :             // this withdrawal is for error recovery, not composing with L2 dapps, so we ignore the return value
-      97                 :          0 :             triggerWithdrawal(l1ERC20, address(this), _from, _amount, "");
-      98                 :          0 :             return true;
-      99                 :            :         }
-     100                 :            :     }
-     101                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2GatewayRouter.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2GatewayRouter.sol.func-sort-c.html deleted file mode 100644 index 448b12e8be..0000000000 --- a/coverage/arbitrum/gateway/L2GatewayRouter.sol.func-sort-c.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2GatewayRouter.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:080.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2GatewayRouter.initialize0
L2GatewayRouter.outboundTransfer0
L2GatewayRouter.setDefaultGateway0
L2GatewayRouter.setGateway0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2GatewayRouter.sol.func.html b/coverage/arbitrum/gateway/L2GatewayRouter.sol.func.html deleted file mode 100644 index 2174662732..0000000000 --- a/coverage/arbitrum/gateway/L2GatewayRouter.sol.func.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2GatewayRouter.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:080.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2GatewayRouter.initialize0
L2GatewayRouter.outboundTransfer0
L2GatewayRouter.setDefaultGateway0
L2GatewayRouter.setGateway0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2GatewayRouter.sol.gcov.html b/coverage/arbitrum/gateway/L2GatewayRouter.sol.gcov.html deleted file mode 100644 index 29af200b61..0000000000 --- a/coverage/arbitrum/gateway/L2GatewayRouter.sol.gcov.html +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2GatewayRouter.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:080.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:020.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../../libraries/gateway/GatewayRouter.sol";
-      22                 :            : import "../../ethereum/gateway/L1GatewayRouter.sol";
-      23                 :            : import "../L2ArbitrumMessenger.sol";
-      24                 :            : import "../../libraries/AddressAliasHelper.sol";
-      25                 :            : 
-      26                 :            : /**
-      27                 :            :  * @title Handles withdrawals from Ethereum into Arbitrum. Tokens are routered to their appropriate L2 gateway (Router itself also conforms to the Gateway interface).
-      28                 :            :  * @notice Router also serves as an L2-L1 token address oracle.
-      29                 :            :  */
-      30                 :            : contract L2GatewayRouter is GatewayRouter, L2ArbitrumMessenger {
-      31                 :            :     modifier onlyCounterpartGateway() override {
-      32                 :            :         require(
-      33                 :            :             msg.sender == AddressAliasHelper.applyL1ToL2Alias(counterpartGateway),
-      34                 :            :             "ONLY_COUNTERPART_GATEWAY"
-      35                 :            :         );
-      36                 :            :         _;
-      37                 :            :     }
-      38                 :            : 
-      39                 :            :     function initialize(address _counterpartGateway, address _defaultGateway) public {
-      40                 :          0 :         GatewayRouter._initialize(_counterpartGateway, address(0), _defaultGateway);
-      41                 :            :     }
-      42                 :            : 
-      43                 :            :     function setGateway(address[] memory _l1Token, address[] memory _gateway)
-      44                 :            :         external
-      45                 :            :         onlyCounterpartGateway
-      46                 :            :     {
-      47                 :            :         // counterpart gateway (L1 router) should never allow wrong lengths
-      48         [ #  # ]:          0 :         assert(_l1Token.length == _gateway.length);
-      49                 :            : 
-      50                 :          0 :         for (uint256 i = 0; i < _l1Token.length; i++) {
-      51                 :          0 :             l1TokenToGateway[_l1Token[i]] = _gateway[i];
-      52                 :          0 :             emit GatewaySet(_l1Token[i], _gateway[i]);
-      53                 :            :         }
-      54                 :            :     }
-      55                 :            : 
-      56                 :            :     function outboundTransfer(
-      57                 :            :         address _l1Token,
-      58                 :            :         address _to,
-      59                 :            :         uint256 _amount,
-      60                 :            :         bytes calldata _data
-      61                 :            :     ) public payable returns (bytes memory) {
-      62                 :          0 :         return outboundTransfer(_l1Token, _to, _amount, 0, 0, _data);
-      63                 :            :     }
-      64                 :            : 
-      65                 :            :     function setDefaultGateway(address newL2DefaultGateway) external onlyCounterpartGateway {
-      66                 :          0 :         defaultGateway = newL2DefaultGateway;
-      67                 :          0 :         emit DefaultGatewayUpdated(newL2DefaultGateway);
-      68                 :            :     }
-      69                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func-sort-c.html deleted file mode 100644 index abcd02a31b..0000000000 --- a/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2ReverseCustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:050.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2ReverseCustomGateway.inboundEscrowTransfer0
L2ReverseCustomGateway.outboundEscrowTransfer0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func.html b/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func.html deleted file mode 100644 index ddf52efc9d..0000000000 --- a/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2ReverseCustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:050.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2ReverseCustomGateway.inboundEscrowTransfer0
L2ReverseCustomGateway.outboundEscrowTransfer0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.gcov.html b/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.gcov.html deleted file mode 100644 index 19078f2953..0000000000 --- a/coverage/arbitrum/gateway/L2ReverseCustomGateway.sol.gcov.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2ReverseCustomGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:050.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./L2CustomGateway.sol";
-      22                 :            : import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
-      23                 :            : 
-      24                 :            : /**
-      25                 :            :  * @title   L2 Gateway for reverse "custom" bridging functionality
-      26                 :            :  * @notice  Handles some (but not all!) reverse custom Gateway needs.
-      27                 :            :  *          Use the reverse custom gateway instead of the normal custom
-      28                 :            :  *          gateway if you want total supply to be tracked on the L2
-      29                 :            :  *          rather than the L1.
-      30                 :            :  * @dev     The reverse custom gateway burns on the l2 and escrows on the l1
-      31                 :            :  *          which is the opposite of the way the normal custom gateway works
-      32                 :            :  *          This means that the total supply L2 isn't affected by briding, which
-      33                 :            :  *          is helpful for obeservers calculating the total supply especially if
-      34                 :            :  *          if minting is also occuring on L2
-      35                 :            :  */
-      36                 :            : contract L2ReverseCustomGateway is L2CustomGateway {
-      37                 :            :     using SafeERC20 for IERC20;
-      38                 :            : 
-      39                 :            :     function inboundEscrowTransfer(
-      40                 :            :         address _l2Token,
-      41                 :            :         address _dest,
-      42                 :            :         uint256 _amount
-      43                 :            :     ) internal virtual override {
-      44                 :          0 :         IERC20(_l2Token).safeTransfer(_dest, _amount);
-      45                 :            :     }
-      46                 :            : 
-      47                 :            :     function outboundEscrowTransfer(
-      48                 :            :         address _l2Token,
-      49                 :            :         address _from,
-      50                 :            :         uint256 _amount
-      51                 :            :     ) internal override returns (uint256) {
-      52                 :          0 :         uint256 prevBalance = IERC20(_l2Token).balanceOf(address(this));
-      53                 :            :         // as in the normal custom gateway, in the reverse custom gateway we check
-      54                 :            :         // for the balances of tokens to ensure that inflationary / deflationary changes in the amount
-      55                 :            :         // are taken into account we ignore the return value since we actually query the token before
-      56                 :            :         // and after to calculate the amount of tokens that were transferred
-      57                 :          0 :         IERC20(_l2Token).safeTransferFrom(_from, address(this), _amount);
-      58                 :          0 :         uint256 postBalance = IERC20(_l2Token).balanceOf(address(this));
-      59                 :          0 :         return postBalance - prevBalance;
-      60                 :            :     }
-      61                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2WethGateway.sol.func-sort-c.html b/coverage/arbitrum/gateway/L2WethGateway.sol.func-sort-c.html deleted file mode 100644 index 67b6692cd5..0000000000 --- a/coverage/arbitrum/gateway/L2WethGateway.sol.func-sort-c.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2WethGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2WethGateway.calculateL2TokenAddress0
L2WethGateway.createOutboundTx0
L2WethGateway.handleNoContract0
L2WethGateway.inboundEscrowTransfer0
L2WethGateway.initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2WethGateway.sol.func.html b/coverage/arbitrum/gateway/L2WethGateway.sol.func.html deleted file mode 100644 index b031cb0c4d..0000000000 --- a/coverage/arbitrum/gateway/L2WethGateway.sol.func.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2WethGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2WethGateway.calculateL2TokenAddress0
L2WethGateway.createOutboundTx0
L2WethGateway.handleNoContract0
L2WethGateway.inboundEscrowTransfer0
L2WethGateway.initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/L2WethGateway.sol.gcov.html b/coverage/arbitrum/gateway/L2WethGateway.sol.gcov.html deleted file mode 100644 index 51e1459e61..0000000000 --- a/coverage/arbitrum/gateway/L2WethGateway.sol.gcov.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway/L2WethGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gateway - L2WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0140.0 %
Date:2023-04-27 16:26:32Functions:050.0 %
Branches:060.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./L2ArbitrumGateway.sol";
-      22                 :            : import "../../libraries/IWETH9.sol";
-      23                 :            : import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
-      24                 :            : import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
-      25                 :            : 
-      26                 :            : contract L2WethGateway is L2ArbitrumGateway {
-      27                 :            :     using SafeERC20 for IERC20;
-      28                 :            : 
-      29                 :            :     address public l1Weth;
-      30                 :            :     address public l2Weth;
-      31                 :            : 
-      32                 :            :     function initialize(
-      33                 :            :         address _l1Counterpart,
-      34                 :            :         address _router,
-      35                 :            :         address _l1Weth,
-      36                 :            :         address _l2Weth
-      37                 :            :     ) public {
-      38                 :          0 :         L2ArbitrumGateway._initialize(_l1Counterpart, _router);
-      39         [ #  # ]:          0 :         require(_l1Weth != address(0), "INVALID_L1WETH");
-      40         [ #  # ]:          0 :         require(_l2Weth != address(0), "INVALID_L2WETH");
-      41                 :          0 :         l1Weth = _l1Weth;
-      42                 :          0 :         l2Weth = _l2Weth;
-      43                 :            :     }
-      44                 :            : 
-      45                 :            :     /**
-      46                 :            :      * @notice internal utility function used to handle when no contract is deployed at expected address
-      47                 :            :      * @param l1ERC20 L1 address of ERC20
-      48                 :            :      */
-      49                 :            :     function handleNoContract(
-      50                 :            :         address l1ERC20,
-      51                 :            :         address, /* expectedL2Address */
-      52                 :            :         address _from,
-      53                 :            :         address, /* _to */
-      54                 :            :         uint256 _amount,
-      55                 :            :         bytes memory /* deployData */
-      56                 :            :     ) internal override returns (bool shouldHalt) {
-      57                 :            :         // it is assumed that the custom token is deployed in the L2 before deposits are made
-      58                 :            :         // trigger withdrawal
-      59                 :            :         // this codepath should only be hit if the system is setup incorrectly
-      60                 :            :         // this withdrawal is for error recovery, not composing with L2 dapps, so we ignore the return value
-      61                 :          0 :         triggerWithdrawal(l1ERC20, address(this), _from, _amount, "");
-      62                 :          0 :         return true;
-      63                 :            :     }
-      64                 :            : 
-      65                 :            :     /**
-      66                 :            :      * @notice Calculate the address used when bridging an ERC20 token
-      67                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
-      68                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
-      69                 :            :      * @param l1ERC20 address of L1 token
-      70                 :            :      * @return L2 address of a bridged ERC20 token
-      71                 :            :      */
-      72                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override returns (address) {
-      73         [ #  # ]:          0 :         if (l1ERC20 != l1Weth) {
-      74                 :            :             // invalid L1 weth address
-      75                 :          0 :             return address(0);
-      76                 :            :         }
-      77                 :          0 :         return l2Weth;
-      78                 :            :     }
-      79                 :            : 
-      80                 :            :     function inboundEscrowTransfer(
-      81                 :            :         address _l2TokenAddress,
-      82                 :            :         address _dest,
-      83                 :            :         uint256 _amount
-      84                 :            :     ) internal override {
-      85                 :          0 :         IWETH9(_l2TokenAddress).deposit{ value: _amount }();
-      86                 :          0 :         IERC20(_l2TokenAddress).safeTransfer(_dest, _amount);
-      87                 :            :     }
-      88                 :            : 
-      89                 :            :     function createOutboundTx(
-      90                 :            :         address _from,
-      91                 :            :         uint256 _tokenAmount,
-      92                 :            :         bytes memory _outboundCalldata
-      93                 :            :     ) internal override returns (uint256) {
-      94                 :            :         // exitNum incremented after being included in _outboundCalldata
-      95                 :          0 :         exitNum++;
-      96                 :          0 :         return
-      97                 :            :             sendTxToL1(
-      98                 :            :                 // we send the amount of weth withdrawn as callvalue to the L1 gateway
-      99                 :            :                 _tokenAmount,
-     100                 :            :                 _from,
-     101                 :            :                 counterpartGateway,
-     102                 :            :                 _outboundCalldata
-     103                 :            :             );
-     104                 :            :     }
-     105                 :            : 
-     106                 :            :     receive() external payable {}
-     107                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/index-sort-b.html b/coverage/arbitrum/gateway/index-sort-b.html deleted file mode 100644 index 5c31eef1d9..0000000000 --- a/coverage/arbitrum/gateway/index-sort-b.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gatewayHitTotalCoverage
Test:lcov.infoLines:0980.0 %
Date:2023-04-27 16:26:32Functions:0290.0 %
Branches:0380.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2GatewayRouter.sol -
0.0%
-
0.0 %0 / 80.0 %0 / 40.0 %0 / 2
L2ERC20Gateway.sol -
0.0%
-
0.0 %0 / 130.0 %0 / 50.0 %0 / 4
L2WethGateway.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 50.0 %0 / 6
L2ArbitrumGateway.sol -
0.0%
-
0.0 %0 / 510.0 %0 / 90.0 %0 / 26
L2CustomGateway.sol -
0.0%
-
0.0 %0 / 70.0 %0 / 4-0 / 0
L2ReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 50.0 %0 / 2-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/index-sort-f.html b/coverage/arbitrum/gateway/index-sort-f.html deleted file mode 100644 index 1370b54700..0000000000 --- a/coverage/arbitrum/gateway/index-sort-f.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gatewayHitTotalCoverage
Test:lcov.infoLines:0980.0 %
Date:2023-04-27 16:26:32Functions:0290.0 %
Branches:0380.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 50.0 %0 / 2-0 / 0
L2GatewayRouter.sol -
0.0%
-
0.0 %0 / 80.0 %0 / 40.0 %0 / 2
L2CustomGateway.sol -
0.0%
-
0.0 %0 / 70.0 %0 / 4-0 / 0
L2ERC20Gateway.sol -
0.0%
-
0.0 %0 / 130.0 %0 / 50.0 %0 / 4
L2WethGateway.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 50.0 %0 / 6
L2ArbitrumGateway.sol -
0.0%
-
0.0 %0 / 510.0 %0 / 90.0 %0 / 26
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/index-sort-l.html b/coverage/arbitrum/gateway/index-sort-l.html deleted file mode 100644 index 10db529782..0000000000 --- a/coverage/arbitrum/gateway/index-sort-l.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gatewayHitTotalCoverage
Test:lcov.infoLines:0980.0 %
Date:2023-04-27 16:26:32Functions:0290.0 %
Branches:0380.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 50.0 %0 / 2-0 / 0
L2CustomGateway.sol -
0.0%
-
0.0 %0 / 70.0 %0 / 4-0 / 0
L2GatewayRouter.sol -
0.0%
-
0.0 %0 / 80.0 %0 / 40.0 %0 / 2
L2ERC20Gateway.sol -
0.0%
-
0.0 %0 / 130.0 %0 / 50.0 %0 / 4
L2WethGateway.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 50.0 %0 / 6
L2ArbitrumGateway.sol -
0.0%
-
0.0 %0 / 510.0 %0 / 90.0 %0 / 26
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/gateway/index.html b/coverage/arbitrum/gateway/index.html deleted file mode 100644 index 2f8d88b1ce..0000000000 --- a/coverage/arbitrum/gateway/index.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrum/gatewayHitTotalCoverage
Test:lcov.infoLines:0980.0 %
Date:2023-04-27 16:26:32Functions:0290.0 %
Branches:0380.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ArbitrumGateway.sol -
0.0%
-
0.0 %0 / 510.0 %0 / 90.0 %0 / 26
L2CustomGateway.sol -
0.0%
-
0.0 %0 / 70.0 %0 / 4-0 / 0
L2ERC20Gateway.sol -
0.0%
-
0.0 %0 / 130.0 %0 / 50.0 %0 / 4
L2GatewayRouter.sol -
0.0%
-
0.0 %0 / 80.0 %0 / 40.0 %0 / 2
L2ReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 50.0 %0 / 2-0 / 0
L2WethGateway.sol -
0.0%
-
0.0 %0 / 140.0 %0 / 50.0 %0 / 6
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/index-sort-b.html b/coverage/arbitrum/index-sort-b.html deleted file mode 100644 index 276e3696f8..0000000000 --- a/coverage/arbitrum/index-sort-b.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrumHitTotalCoverage
Test:lcov.infoLines:0170.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
StandardArbERC20.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 40.0 %0 / 6
L2ArbitrumMessenger.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 1-0 / 0
ReverseArbToken.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/index-sort-f.html b/coverage/arbitrum/index-sort-f.html deleted file mode 100644 index c747ddb47a..0000000000 --- a/coverage/arbitrum/index-sort-f.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrumHitTotalCoverage
Test:lcov.infoLines:0170.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ArbitrumMessenger.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 1-0 / 0
ReverseArbToken.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
StandardArbERC20.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 40.0 %0 / 6
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/index-sort-l.html b/coverage/arbitrum/index-sort-l.html deleted file mode 100644 index 9388bebc75..0000000000 --- a/coverage/arbitrum/index-sort-l.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrumHitTotalCoverage
Test:lcov.infoLines:0170.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
ReverseArbToken.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
L2ArbitrumMessenger.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 1-0 / 0
StandardArbERC20.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 40.0 %0 / 6
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/arbitrum/index.html b/coverage/arbitrum/index.html deleted file mode 100644 index d5fd659753..0000000000 --- a/coverage/arbitrum/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - arbitrum - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - arbitrumHitTotalCoverage
Test:lcov.infoLines:0170.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2ArbitrumMessenger.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 1-0 / 0
ReverseArbToken.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
StandardArbERC20.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 40.0 %0 / 6
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/emerald.png b/coverage/emerald.png deleted file mode 100644 index 38ad4f4068b935643d2486f323005fb294a9bd7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^Jb!lvI6;R0X`wF(yt=9xVZRt1vCRixIA4P dLn>}1Cji+@42)0J?}79&c)I$ztaD0e0sy@GAL0N2 diff --git a/coverage/ethereum/L1ArbitrumMessenger.sol.func-sort-c.html b/coverage/ethereum/L1ArbitrumMessenger.sol.func-sort-c.html deleted file mode 100644 index e59cc4d84e..0000000000 --- a/coverage/ethereum/L1ArbitrumMessenger.sol.func-sort-c.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/L1ArbitrumMessenger.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum - L1ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumMessenger.getL2ToL1Sender4
L1ArbitrumMessenger.getBridge10
L1ArbitrumMessenger._createRetryable15
L1ArbitrumMessenger.sendTxToL220
L1ArbitrumMessenger.sendTxToL2CustomRefund21
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/L1ArbitrumMessenger.sol.func.html b/coverage/ethereum/L1ArbitrumMessenger.sol.func.html deleted file mode 100644 index 6ab5f1e884..0000000000 --- a/coverage/ethereum/L1ArbitrumMessenger.sol.func.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/L1ArbitrumMessenger.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum - L1ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumMessenger._createRetryable15
L1ArbitrumMessenger.getBridge10
L1ArbitrumMessenger.getL2ToL1Sender4
L1ArbitrumMessenger.sendTxToL220
L1ArbitrumMessenger.sendTxToL2CustomRefund21
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/L1ArbitrumMessenger.sol.gcov.html b/coverage/ethereum/L1ArbitrumMessenger.sol.gcov.html deleted file mode 100644 index 740132cfbd..0000000000 --- a/coverage/ethereum/L1ArbitrumMessenger.sol.gcov.html +++ /dev/null @@ -1,302 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/L1ArbitrumMessenger.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum - L1ArbitrumMessenger.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "@arbitrum/nitro-contracts/src/bridge/IInbox.sol";
-      22                 :            : import "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol";
-      23                 :            : 
-      24                 :            : /// @notice L1 utility contract to assist with L1 <=> L2 interactions
-      25                 :            : /// @dev this is an abstract contract instead of library so the functions can be easily overriden when testing
-      26                 :            : abstract contract L1ArbitrumMessenger {
-      27                 :            :     event TxToL2(address indexed _from, address indexed _to, uint256 indexed _seqNum, bytes _data);
-      28                 :            : 
-      29                 :            :     struct L2GasParams {
-      30                 :            :         uint256 _maxSubmissionCost;
-      31                 :            :         uint256 _maxGas;
-      32                 :            :         uint256 _gasPriceBid;
-      33                 :            :     }
-      34                 :            : 
-      35                 :            :     function sendTxToL2CustomRefund(
-      36                 :            :         address _inbox,
-      37                 :            :         address _to,
-      38                 :            :         address _refundTo,
-      39                 :            :         address _user,
-      40                 :            :         uint256 _l1CallValue,
-      41                 :            :         uint256 _l2CallValue,
-      42                 :            :         L2GasParams memory _l2GasParams,
-      43                 :            :         bytes memory _data
-      44                 :            :     ) internal returns (uint256) {
-      45                 :            :         // alternative function entry point when struggling with the stack size
-      46                 :          4 :         return
-      47                 :            :             sendTxToL2CustomRefund(
-      48                 :            :                 _inbox,
-      49                 :            :                 _to,
-      50                 :            :                 _refundTo,
-      51                 :            :                 _user,
-      52                 :            :                 _l1CallValue,
-      53                 :            :                 _l2CallValue,
-      54                 :            :                 _l2GasParams._maxSubmissionCost,
-      55                 :            :                 _l2GasParams._maxGas,
-      56                 :            :                 _l2GasParams._gasPriceBid,
-      57                 :            :                 _data
-      58                 :            :             );
-      59                 :            :     }
-      60                 :            : 
-      61                 :            :     function sendTxToL2(
-      62                 :            :         address _inbox,
-      63                 :            :         address _to,
-      64                 :            :         address _user,
-      65                 :            :         uint256 _l1CallValue,
-      66                 :            :         uint256 _l2CallValue,
-      67                 :            :         L2GasParams memory _l2GasParams,
-      68                 :            :         bytes memory _data
-      69                 :            :     ) internal returns (uint256) {
-      70                 :            :         // alternative function entry point when struggling with the stack size
-      71                 :          7 :         return
-      72                 :            :             sendTxToL2(
-      73                 :            :                 _inbox,
-      74                 :            :                 _to,
-      75                 :            :                 _user,
-      76                 :            :                 _l1CallValue,
-      77                 :            :                 _l2CallValue,
-      78                 :            :                 _l2GasParams._maxSubmissionCost,
-      79                 :            :                 _l2GasParams._maxGas,
-      80                 :            :                 _l2GasParams._gasPriceBid,
-      81                 :            :                 _data
-      82                 :            :             );
-      83                 :            :     }
-      84                 :            : 
-      85                 :            :     function sendTxToL2CustomRefund(
-      86                 :            :         address _inbox,
-      87                 :            :         address _to,
-      88                 :            :         address _refundTo,
-      89                 :            :         address _user,
-      90                 :            :         uint256 _l1CallValue,
-      91                 :            :         uint256 _l2CallValue,
-      92                 :            :         uint256 _maxSubmissionCost,
-      93                 :            :         uint256 _maxGas,
-      94                 :            :         uint256 _gasPriceBid,
-      95                 :            :         bytes memory _data
-      96                 :            :     ) internal returns (uint256) {
-      97                 :         17 :         uint256 seqNum = _createRetryable(
-      98                 :            :             _inbox,
-      99                 :            :             _to,
-     100                 :            :             _refundTo,
-     101                 :            :             _user,
-     102                 :            :             _l1CallValue,
-     103                 :            :             _l2CallValue,
-     104                 :            :             _maxSubmissionCost,
-     105                 :            :             _maxGas,
-     106                 :            :             _gasPriceBid,
-     107                 :            :             _data
-     108                 :            :         );
-     109                 :         17 :         emit TxToL2(_user, _to, seqNum, _data);
-     110                 :         17 :         return seqNum;
-     111                 :            :     }
-     112                 :            : 
-     113                 :            :     function sendTxToL2(
-     114                 :            :         address _inbox,
-     115                 :            :         address _to,
-     116                 :            :         address _user,
-     117                 :            :         uint256 _l1CallValue,
-     118                 :            :         uint256 _l2CallValue,
-     119                 :            :         uint256 _maxSubmissionCost,
-     120                 :            :         uint256 _maxGas,
-     121                 :            :         uint256 _gasPriceBid,
-     122                 :            :         bytes memory _data
-     123                 :            :     ) internal returns (uint256) {
-     124                 :         13 :         return
-     125                 :            :             sendTxToL2CustomRefund(
-     126                 :            :                 _inbox,
-     127                 :            :                 _to,
-     128                 :            :                 _user,
-     129                 :            :                 _user,
-     130                 :            :                 _l1CallValue,
-     131                 :            :                 _l2CallValue,
-     132                 :            :                 _maxSubmissionCost,
-     133                 :            :                 _maxGas,
-     134                 :            :                 _gasPriceBid,
-     135                 :            :                 _data
-     136                 :            :             );
-     137                 :            :     }
-     138                 :            : 
-     139                 :            :     function getBridge(address _inbox) internal view returns (IBridge) {
-     140                 :         10 :         return IInbox(_inbox).bridge();
-     141                 :            :     }
-     142                 :            : 
-     143                 :            :     /// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
-     144                 :            :     function getL2ToL1Sender(address _inbox) internal view returns (address) {
-     145                 :          4 :         IOutbox outbox = IOutbox(getBridge(_inbox).activeOutbox());
-     146                 :          4 :         address l2ToL1Sender = outbox.l2ToL1Sender();
-     147                 :            : 
-     148         [ #  + ]:          4 :         require(l2ToL1Sender != address(0), "NO_SENDER");
-     149                 :          4 :         return l2ToL1Sender;
-     150                 :            :     }
-     151                 :            : 
-     152                 :            :     /**
-     153                 :            :      * @notice Calls inbox to create retryable ticket. Default implementation is for standard Eth-based rollup, but it can be overriden to create retryable in ERC20-based rollup.
-     154                 :            :      * @param _inbox address of the rollup's inbox
-     155                 :            :      * @param _to destination L2 contract address
-     156                 :            :      * @param _refundTo refund address for excess fee
-     157                 :            :      * @param _user refund address for callvalue
-     158                 :            :      * @param _totalFeeAmount amount of fees to pay, in Eth or native token, for retryable's execution
-     159                 :            :      * @param _l2CallValue call value for retryable L2 message
-     160                 :            :      * @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
-     161                 :            :      * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution
-     162                 :            :      * @param _gasPriceBid price bid for L2 execution
-     163                 :            :      * @param _data ABI encoded data of L2 message
-     164                 :            :      * @return unique message number of the retryable transaction
-     165                 :            :      */
-     166                 :            :     function _createRetryable(
-     167                 :            :         address _inbox,
-     168                 :            :         address _to,
-     169                 :            :         address _refundTo,
-     170                 :            :         address _user,
-     171                 :            :         uint256 _totalFeeAmount,
-     172                 :            :         uint256 _l2CallValue,
-     173                 :            :         uint256 _maxSubmissionCost,
-     174                 :            :         uint256 _maxGas,
-     175                 :            :         uint256 _gasPriceBid,
-     176                 :            :         bytes memory _data
-     177                 :            :     ) internal virtual returns (uint256) {
-     178                 :         15 :         return
-     179                 :            :             IEthInbox(_inbox).createRetryableTicket{ value: _totalFeeAmount }(
-     180                 :            :                 _to,
-     181                 :            :                 _l2CallValue,
-     182                 :            :                 _maxSubmissionCost,
-     183                 :            :                 _refundTo,
-     184                 :            :                 _user,
-     185                 :            :                 _maxGas,
-     186                 :            :                 _gasPriceBid,
-     187                 :            :                 _data
-     188                 :            :             );
-     189                 :            :     }
-     190                 :            : }
-     191                 :            : 
-     192                 :            : interface IERC20Inbox {
-     193                 :            :     function createRetryableTicket(
-     194                 :            :         address to,
-     195                 :            :         uint256 l2CallValue,
-     196                 :            :         uint256 maxSubmissionCost,
-     197                 :            :         address excessFeeRefundAddress,
-     198                 :            :         address callValueRefundAddress,
-     199                 :            :         uint256 gasLimit,
-     200                 :            :         uint256 maxFeePerGas,
-     201                 :            :         uint256 tokenTotalFeeAmount,
-     202                 :            :         bytes calldata data
-     203                 :            :     ) external returns (uint256);
-     204                 :            : }
-     205                 :            : 
-     206                 :            : interface IEthInbox {
-     207                 :            :     function createRetryableTicket(
-     208                 :            :         address to,
-     209                 :            :         uint256 l2CallValue,
-     210                 :            :         uint256 maxSubmissionCost,
-     211                 :            :         address excessFeeRefundAddress,
-     212                 :            :         address callValueRefundAddress,
-     213                 :            :         uint256 gasLimit,
-     214                 :            :         uint256 maxFeePerGas,
-     215                 :            :         bytes calldata data
-     216                 :            :     ) external payable returns (uint256);
-     217                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func-sort-c.html deleted file mode 100644 index 9018b92e80..0000000000 --- a/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func-sort-c.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ArbitrumExtendedGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ArbitrumExtendedGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1717100.0 %
Date:2023-04-27 16:26:32Functions:44100.0 %
Branches:101283.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumExtendedGateway.encodeWithdrawal512
L1ArbitrumExtendedGateway.getExternalCall1024
L1ArbitrumExtendedGateway.setRedirectedExit5632
L1ArbitrumExtendedGateway.transferExitAndCall5636
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func.html b/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func.html deleted file mode 100644 index 172a5e10af..0000000000 --- a/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.func.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ArbitrumExtendedGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ArbitrumExtendedGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1717100.0 %
Date:2023-04-27 16:26:32Functions:44100.0 %
Branches:101283.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumExtendedGateway.encodeWithdrawal512
L1ArbitrumExtendedGateway.getExternalCall1024
L1ArbitrumExtendedGateway.setRedirectedExit5632
L1ArbitrumExtendedGateway.transferExitAndCall5636
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.gcov.html b/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.gcov.html deleted file mode 100644 index aeb06de666..0000000000 --- a/coverage/ethereum/gateway/L1ArbitrumExtendedGateway.sol.gcov.html +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ArbitrumExtendedGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ArbitrumExtendedGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1717100.0 %
Date:2023-04-27 16:26:32Functions:44100.0 %
Branches:101283.3 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../../libraries/ITransferAndCall.sol";
-      22                 :            : 
-      23                 :            : import "./L1ArbitrumGateway.sol";
-      24                 :            : 
-      25                 :            : interface ITradeableExitReceiver {
-      26                 :            :     function onExitTransfer(
-      27                 :            :         address sender,
-      28                 :            :         uint256 exitNum,
-      29                 :            :         bytes calldata data
-      30                 :            :     ) external returns (bool);
-      31                 :            : }
-      32                 :            : 
-      33                 :            : abstract contract L1ArbitrumExtendedGateway is L1ArbitrumGateway {
-      34                 :            :     struct ExitData {
-      35                 :            :         bool isExit;
-      36                 :            :         address _newTo;
-      37                 :            :         bytes _newData;
-      38                 :            :     }
-      39                 :            : 
-      40                 :            :     mapping(bytes32 => ExitData) public redirectedExits;
-      41                 :            : 
-      42                 :            :     event WithdrawRedirected(
-      43                 :            :         address indexed from,
-      44                 :            :         address indexed to,
-      45                 :            :         uint256 indexed exitNum,
-      46                 :            :         bytes newData,
-      47                 :            :         bytes data,
-      48                 :            :         bool madeExternalCall
-      49                 :            :     );
-      50                 :            : 
-      51                 :            :     /**
-      52                 :            :      * @notice Allows a user to redirect their right to claim a withdrawal to another address.
-      53                 :            :      * @dev This method also allows you to make an arbitrary call after the transfer.
-      54                 :            :      * This does not validate if the exit was already triggered. It is assumed the `_exitNum` is
-      55                 :            :      * validated off-chain to ensure this was not yet triggered.
-      56                 :            :      * @param _exitNum Sequentially increasing exit counter determined by the L2 bridge
-      57                 :            :      * @param _initialDestination address the L2 withdrawal call initially set as the destination.
-      58                 :            :      * @param _newDestination address the L1 will now call instead of the previously set destination
-      59                 :            :      * @param _newData data to be used in inboundEscrowAndCall
-      60                 :            :      * @param _data optional data for external call upon transfering the exit
-      61                 :            :      */
-      62                 :            :     function transferExitAndCall(
-      63                 :            :         uint256 _exitNum,
-      64                 :            :         address _initialDestination,
-      65                 :            :         address _newDestination,
-      66                 :            :         bytes calldata _newData,
-      67                 :            :         bytes calldata _data
-      68                 :            :     ) external {
-      69                 :            :         // the initial data doesn't make a difference when transfering you exit
-      70                 :            :         // since the L2 bridge gives a unique exit ID to each exit
-      71                 :       5636 :         (address expectedSender, ) = getExternalCall(_exitNum, _initialDestination, "");
-      72                 :            : 
-      73                 :            :         // if you want to transfer your exit, you must be the current destination
-      74         [ +  + ]:       5636 :         require(msg.sender == expectedSender, "NOT_EXPECTED_SENDER");
-      75                 :            :         // the inboundEscrowAndCall functionality has been disabled, so no data is allowed
-      76         [ +  + ]:       5634 :         require(_newData.length == 0, "NO_DATA_ALLOWED");
-      77                 :            : 
-      78                 :       5632 :         setRedirectedExit(_exitNum, _initialDestination, _newDestination, _newData);
-      79                 :            : 
-      80         [ +  + ]:       5632 :         if (_data.length > 0) {
-      81         [ +  + ]:       3584 :             require(Address.isContract(_newDestination), "TO_NOT_CONTRACT");
-      82                 :       3072 :             bool success = ITradeableExitReceiver(_newDestination).onExitTransfer(
-      83                 :            :                 expectedSender,
-      84                 :            :                 _exitNum,
-      85                 :            :                 _data
-      86                 :            :             );
-      87         [ +  + ]:       3072 :             require(success, "TRANSFER_HOOK_FAIL");
-      88                 :            :         }
-      89                 :            : 
-      90                 :       4096 :         emit WithdrawRedirected(
-      91                 :            :             expectedSender,
-      92                 :            :             _newDestination,
-      93                 :            :             _exitNum,
-      94                 :            :             _newData,
-      95                 :            :             _data,
-      96                 :            :             _data.length > 0
-      97                 :            :         );
-      98                 :            :     }
-      99                 :            : 
-     100                 :            :     /// @notice this does not verify if the external call was already done
-     101                 :            :     function getExternalCall(
-     102                 :            :         uint256 _exitNum,
-     103                 :            :         address _initialDestination,
-     104                 :            :         bytes memory _initialData
-     105                 :            :     ) public view virtual override returns (address target, bytes memory data) {
-     106                 :            :         // this function is virtual so that subclasses can override it with custom logic where necessary
-     107                 :       6662 :         bytes32 withdrawData = encodeWithdrawal(_exitNum, _initialDestination);
-     108                 :       6662 :         ExitData storage exit = redirectedExits[withdrawData];
-     109                 :            : 
-     110                 :            :         // here we don't authenticate `_initialData`. we could hash it into `withdrawData` but would increase gas costs
-     111                 :            :         // this is safe because if the exit isn't overriden, the _initialData coming from L2 is trusted
-     112                 :            :         // but if the exit is traded, all we care about is the latest user calldata
-     113         [ #  # ]:       6662 :         if (exit.isExit) {
-     114                 :       2048 :             return (exit._newTo, exit._newData);
-     115                 :            :         } else {
-     116                 :       4614 :             return (_initialDestination, _initialData);
-     117                 :            :         }
-     118                 :            :     }
-     119                 :            : 
-     120                 :            :     function setRedirectedExit(
-     121                 :            :         uint256 _exitNum,
-     122                 :            :         address _initialDestination,
-     123                 :            :         address _newDestination,
-     124                 :            :         bytes memory _newData
-     125                 :            :     ) internal virtual {
-     126                 :       5632 :         bytes32 withdrawData = encodeWithdrawal(_exitNum, _initialDestination);
-     127                 :       5632 :         redirectedExits[withdrawData] = ExitData(true, _newDestination, _newData);
-     128                 :            :     }
-     129                 :            : 
-     130                 :            :     function encodeWithdrawal(uint256 _exitNum, address _initialDestination)
-     131                 :            :         public
-     132                 :            :         pure
-     133                 :            :         returns (bytes32)
-     134                 :            :     {
-     135                 :            :         // here we assume the L2 bridge gives a unique exitNum to each exit
-     136                 :      12806 :         return keccak256(abi.encode(_exitNum, _initialDestination));
-     137                 :            :     }
-     138                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func-sort-c.html deleted file mode 100644 index f06d2d0644..0000000000 --- a/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func-sort-c.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ArbitrumGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:394881.2 %
Date:2023-04-27 16:26:32Functions:111478.6 %
Branches:121866.7 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumGateway.createOutboundTx0
L1ArbitrumGateway.getExternalCall0
L1ArbitrumGateway.getOutboundCalldata0
L1ArbitrumGateway._initiateDeposit2
L1ArbitrumGateway.createOutboundTxCustomRefund2
L1ArbitrumGateway.inboundEscrowTransfer2
L1ArbitrumGateway.outboundTransfer2
L1ArbitrumGateway.postUpgradeInit2
L1ArbitrumGateway._parseUserEncodedData5
L1ArbitrumGateway.finalizeInboundTransfer6
L1ArbitrumGateway.outboundEscrowTransfer6
L1ArbitrumGateway.outboundTransferCustomRefund12
L1ArbitrumGateway._initialize13
L1ArbitrumGateway.supportsInterface512
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func.html b/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func.html deleted file mode 100644 index 1824185b33..0000000000 --- a/coverage/ethereum/gateway/L1ArbitrumGateway.sol.func.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ArbitrumGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:394881.2 %
Date:2023-04-27 16:26:32Functions:111478.6 %
Branches:121866.7 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ArbitrumGateway._initialize13
L1ArbitrumGateway._initiateDeposit2
L1ArbitrumGateway._parseUserEncodedData5
L1ArbitrumGateway.createOutboundTx0
L1ArbitrumGateway.createOutboundTxCustomRefund2
L1ArbitrumGateway.finalizeInboundTransfer6
L1ArbitrumGateway.getExternalCall0
L1ArbitrumGateway.getOutboundCalldata0
L1ArbitrumGateway.inboundEscrowTransfer2
L1ArbitrumGateway.outboundEscrowTransfer6
L1ArbitrumGateway.outboundTransfer2
L1ArbitrumGateway.outboundTransferCustomRefund12
L1ArbitrumGateway.postUpgradeInit2
L1ArbitrumGateway.supportsInterface512
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ArbitrumGateway.sol.gcov.html b/coverage/ethereum/gateway/L1ArbitrumGateway.sol.gcov.html deleted file mode 100644 index 301e533ff0..0000000000 --- a/coverage/ethereum/gateway/L1ArbitrumGateway.sol.gcov.html +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ArbitrumGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ArbitrumGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:394881.2 %
Date:2023-04-27 16:26:32Functions:111478.6 %
Branches:121866.7 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
-      22                 :            : import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
-      23                 :            : import "@openzeppelin/contracts/utils/Create2.sol";
-      24                 :            : import "@openzeppelin/contracts/utils/Address.sol";
-      25                 :            : import "../L1ArbitrumMessenger.sol";
-      26                 :            : import "./IL1ArbitrumGateway.sol";
-      27                 :            : import "../../libraries/ProxyUtil.sol";
-      28                 :            : import "../../libraries/gateway/GatewayMessageHandler.sol";
-      29                 :            : import "../../libraries/gateway/TokenGateway.sol";
-      30                 :            : import "../../libraries/ITransferAndCall.sol";
-      31                 :            : import "../../libraries/ERC165.sol";
-      32                 :            : 
-      33                 :            : /**
-      34                 :            :  * @title Common interface for gatways on L1 messaging to Arbitrum.
-      35                 :            :  */
-      36                 :            : abstract contract L1ArbitrumGateway is
-      37                 :            :     L1ArbitrumMessenger,
-      38                 :            :     TokenGateway,
-      39                 :            :     ERC165,
-      40                 :            :     IL1ArbitrumGateway
-      41                 :            : {
-      42                 :            :     using SafeERC20 for IERC20;
-      43                 :            :     using Address for address;
-      44                 :            : 
-      45                 :            :     address public override inbox;
-      46                 :            : 
-      47                 :            :     event DepositInitiated(
-      48                 :            :         address l1Token,
-      49                 :            :         address indexed _from,
-      50                 :            :         address indexed _to,
-      51                 :            :         uint256 indexed _sequenceNumber,
-      52                 :            :         uint256 _amount
-      53                 :            :     );
-      54                 :            : 
-      55                 :            :     event WithdrawalFinalized(
-      56                 :            :         address l1Token,
-      57                 :            :         address indexed _from,
-      58                 :            :         address indexed _to,
-      59                 :            :         uint256 indexed _exitNum,
-      60                 :            :         uint256 _amount
-      61                 :            :     );
-      62                 :            : 
-      63                 :            :     modifier onlyCounterpartGateway() override {
-      64                 :            :         address _inbox = inbox;
-      65                 :            : 
-      66                 :            :         // a message coming from the counterpart gateway was executed by the bridge
-      67                 :            :         address bridge = address(super.getBridge(_inbox));
-      68                 :            :         require(msg.sender == bridge, "NOT_FROM_BRIDGE");
-      69                 :            : 
-      70                 :            :         // and the outbox reports that the L2 address of the sender is the counterpart gateway
-      71                 :            :         address l2ToL1Sender = super.getL2ToL1Sender(_inbox);
-      72                 :            :         require(l2ToL1Sender == counterpartGateway, "ONLY_COUNTERPART_GATEWAY");
-      73                 :            :         _;
-      74                 :            :     }
-      75                 :            : 
-      76                 :            :     function postUpgradeInit() external {
-      77                 :            :         // it is assumed the L1 Arbitrum Gateway contract is behind a Proxy controlled by a proxy admin
-      78                 :            :         // this function can only be called by the proxy admin contract
-      79                 :          2 :         address proxyAdmin = ProxyUtil.getProxyAdmin();
-      80         [ +  # ]:          2 :         require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");
-      81                 :            :         // this has no other logic since the current upgrade doesn't require this logic
-      82                 :            :     }
-      83                 :            : 
-      84                 :            :     function _initialize(
-      85                 :            :         address _l2Counterpart,
-      86                 :            :         address _router,
-      87                 :            :         address _inbox
-      88                 :            :     ) internal {
-      89                 :         13 :         TokenGateway._initialize(_l2Counterpart, _router);
-      90                 :            :         // L1 gateway must have a router
-      91         [ #  + ]:         13 :         require(_router != address(0), "BAD_ROUTER");
-      92         [ #  + ]:         13 :         require(_inbox != address(0), "BAD_INBOX");
-      93                 :         13 :         inbox = _inbox;
-      94                 :            :     }
-      95                 :            : 
-      96                 :            :     /**
-      97                 :            :      * @notice Finalizes a withdrawal via Outbox message; callable only by L2Gateway.outboundTransfer
-      98                 :            :      * @param _token L1 address of token being withdrawn from
-      99                 :            :      * @param _from initiator of withdrawal
-     100                 :            :      * @param _to address the L2 withdrawal call set as the destination.
-     101                 :            :      * @param _amount Token amount being withdrawn
-     102                 :            :      * @param _data encoded exitNum (Sequentially increasing exit counter determined by the L2Gateway) and additinal hook data
-     103                 :            :      */
-     104                 :            :     function finalizeInboundTransfer(
-     105                 :            :         address _token,
-     106                 :            :         address _from,
-     107                 :            :         address _to,
-     108                 :            :         uint256 _amount,
-     109                 :            :         bytes calldata _data
-     110                 :            :     ) public payable virtual override onlyCounterpartGateway {
-     111                 :            :         // this function is marked as virtual so superclasses can override it to add modifiers
-     112                 :          2 :         (uint256 exitNum, bytes memory callHookData) = GatewayMessageHandler.parseToL1GatewayMsg(
-     113                 :            :             _data
-     114                 :            :         );
-     115                 :            : 
-     116         [ #  + ]:          2 :         if (callHookData.length != 0) {
-     117                 :            :             // callHookData should always be 0 since inboundEscrowAndCall is disabled
-     118                 :          0 :             callHookData = bytes("");
-     119                 :            :         }
-     120                 :            : 
-     121                 :            :         // we ignore the returned data since the callHook feature is now disabled
-     122                 :          2 :         (_to, ) = getExternalCall(exitNum, _to, callHookData);
-     123                 :          2 :         inboundEscrowTransfer(_token, _to, _amount);
-     124                 :            : 
-     125                 :          2 :         emit WithdrawalFinalized(_token, _from, _to, exitNum, _amount);
-     126                 :            :     }
-     127                 :            : 
-     128                 :            :     function getExternalCall(
-     129                 :            :         uint256, /* _exitNum */
-     130                 :            :         address _initialDestination,
-     131                 :            :         bytes memory _initialData
-     132                 :            :     ) public view virtual returns (address target, bytes memory data) {
-     133                 :            :         // this method is virtual so the destination of a call can be changed
-     134                 :            :         // using tradeable exits in a subclass (L1ArbitrumExtendedGateway)
-     135                 :          0 :         target = _initialDestination;
-     136                 :          0 :         data = _initialData;
-     137                 :            :     }
-     138                 :            : 
-     139                 :            :     function inboundEscrowTransfer(
-     140                 :            :         address _l1Token,
-     141                 :            :         address _dest,
-     142                 :            :         uint256 _amount
-     143                 :            :     ) internal virtual {
-     144                 :            :         // this method is virtual since different subclasses can handle escrow differently
-     145                 :          2 :         IERC20(_l1Token).safeTransfer(_dest, _amount);
-     146                 :            :     }
-     147                 :            : 
-     148                 :            :     /**
-     149                 :            :      * @dev Only excess gas is refunded to the _refundTo account, l2 call value is always returned to the _to account
-     150                 :            :      */
-     151                 :            :     function createOutboundTxCustomRefund(
-     152                 :            :         address _refundTo,
-     153                 :            :         address _from,
-     154                 :            :         uint256, /* _tokenAmount */
-     155                 :            :         uint256 _maxGas,
-     156                 :            :         uint256 _gasPriceBid,
-     157                 :            :         uint256 _maxSubmissionCost,
-     158                 :            :         bytes memory _outboundCalldata
-     159                 :            :     ) internal virtual returns (uint256) {
-     160                 :            :         // We make this function virtual since outboundTransfer logic is the same for many gateways
-     161                 :            :         // but sometimes (ie weth) you construct the outgoing message differently.
-     162                 :            : 
-     163                 :            :         // msg.value is sent, but 0 is set to the L2 call value
-     164                 :            :         // the eth sent is used to pay for the tx's gas
-     165                 :          2 :         return
-     166                 :            :             sendTxToL2CustomRefund(
-     167                 :            :                 inbox,
-     168                 :            :                 counterpartGateway,
-     169                 :            :                 _refundTo,
-     170                 :            :                 _from,
-     171                 :            :                 msg.value, // we forward the L1 call value to the inbox
-     172                 :            :                 0, // l2 call value 0 by default
-     173                 :            :                 L2GasParams({
-     174                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
-     175                 :            :                     _maxGas: _maxGas,
-     176                 :            :                     _gasPriceBid: _gasPriceBid
-     177                 :            :                 }),
-     178                 :            :                 _outboundCalldata
-     179                 :            :             );
-     180                 :            :     }
-     181                 :            : 
-     182                 :            :     /**
-     183                 :            :      * @notice DEPRECATED - look at createOutboundTxCustomRefund instead
-     184                 :            :      */
-     185                 :            :     function createOutboundTx(
-     186                 :            :         address _from,
-     187                 :            :         uint256 _tokenAmount,
-     188                 :            :         uint256 _maxGas,
-     189                 :            :         uint256 _gasPriceBid,
-     190                 :            :         uint256 _maxSubmissionCost,
-     191                 :            :         bytes memory _outboundCalldata
-     192                 :            :     ) internal returns (uint256) {
-     193                 :          0 :         return
-     194                 :            :             createOutboundTxCustomRefund(
-     195                 :            :                 _from,
-     196                 :            :                 _from,
-     197                 :            :                 _tokenAmount,
-     198                 :            :                 _maxGas,
-     199                 :            :                 _gasPriceBid,
-     200                 :            :                 _maxSubmissionCost,
-     201                 :            :                 _outboundCalldata
-     202                 :            :             );
-     203                 :            :     }
-     204                 :            : 
-     205                 :            :     /**
-     206                 :            :      * @notice DEPRECATED - look at outboundTransferCustomRefund instead
-     207                 :            :      */
-     208                 :            :     function outboundTransfer(
-     209                 :            :         address _l1Token,
-     210                 :            :         address _to,
-     211                 :            :         uint256 _amount,
-     212                 :            :         uint256 _maxGas,
-     213                 :            :         uint256 _gasPriceBid,
-     214                 :            :         bytes calldata _data
-     215                 :            :     ) public payable override returns (bytes memory res) {
-     216                 :          2 :         return
-     217                 :            :             outboundTransferCustomRefund(_l1Token, _to, _to, _amount, _maxGas, _gasPriceBid, _data);
-     218                 :            :     }
-     219                 :            : 
-     220                 :            :     /**
-     221                 :            :      * @notice Deposit ERC20 token from Ethereum into Arbitrum. If L2 side hasn't been deployed yet, includes name/symbol/decimals data for initial L2 deploy. Initiate by GatewayRouter.
-     222                 :            :      * @dev L2 address alias will not be applied to the following types of addresses on L1:
-     223                 :            :      *      - an externally-owned account
-     224                 :            :      *      - a contract in construction
-     225                 :            :      *      - an address where a contract will be created
-     226                 :            :      *      - an address where a contract lived, but was destroyed
-     227                 :            :      * @param _l1Token L1 address of ERC20
-     228                 :            :      * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2
-     229                 :            :      * @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
-     230                 :            :                   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
-     231                 :            :      * @param _amount Token Amount
-     232                 :            :      * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution
-     233                 :            :      * @param _gasPriceBid Gas price for L2 execution
-     234                 :            :      * @param _data encoded data from router and user
-     235                 :            :      * @return res abi encoded inbox sequence number
-     236                 :            :      */
-     237                 :            :     //  * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
-     238                 :            :     function outboundTransferCustomRefund(
-     239                 :            :         address _l1Token,
-     240                 :            :         address _refundTo,
-     241                 :            :         address _to,
-     242                 :            :         uint256 _amount,
-     243                 :            :         uint256 _maxGas,
-     244                 :            :         uint256 _gasPriceBid,
-     245                 :            :         bytes calldata _data
-     246                 :            :     ) public payable virtual override returns (bytes memory res) {
-     247         [ +  + ]:         12 :         require(isRouter(msg.sender), "NOT_FROM_ROUTER");
-     248                 :            :         // This function is set as public and virtual so that subclasses can override
-     249                 :            :         // it and add custom validation for callers (ie only whitelisted users)
-     250                 :         10 :         address _from;
-     251                 :         10 :         uint256 seqNum;
-     252                 :         10 :         bytes memory extraData;
-     253                 :            :         {
-     254                 :         10 :             uint256 _maxSubmissionCost;
-     255                 :         10 :             uint256 tokenTotalFeeAmount;
-     256         [ +  # ]:         10 :             if (super.isRouter(msg.sender)) {
-     257                 :            :                 // router encoded
-     258                 :         10 :                 (_from, extraData) = GatewayMessageHandler.parseFromRouterToGateway(_data);
-     259                 :            :             } else {
-     260                 :          0 :                 _from = msg.sender;
-     261                 :          0 :                 extraData = _data;
-     262                 :            :             }
-     263                 :            :             // unpack user encoded data
-     264                 :         10 :             (_maxSubmissionCost, extraData, tokenTotalFeeAmount) = _parseUserEncodedData(extraData);
-     265                 :            : 
-     266                 :            :             // the inboundEscrowAndCall functionality has been disabled, so no data is allowed
-     267         [ +  + ]:         10 :             require(extraData.length == 0, "EXTRA_DATA_DISABLED");
-     268                 :            : 
-     269         [ +  + ]:          8 :             require(_l1Token.isContract(), "L1_NOT_CONTRACT");
-     270                 :          6 :             address l2Token = calculateL2TokenAddress(_l1Token);
-     271         [ #  + ]:          6 :             require(l2Token != address(0), "NO_L2_TOKEN_SET");
-     272                 :            : 
-     273                 :          6 :             _amount = outboundEscrowTransfer(_l1Token, _from, _amount);
-     274                 :            : 
-     275                 :            :             // we override the res field to save on the stack
-     276                 :          4 :             res = getOutboundCalldata(_l1Token, _from, _to, _amount, extraData);
-     277                 :            : 
-     278                 :          4 :             seqNum = _initiateDeposit(
-     279                 :            :                 _refundTo,
-     280                 :            :                 _from,
-     281                 :            :                 _amount,
-     282                 :            :                 _maxGas,
-     283                 :            :                 _gasPriceBid,
-     284                 :            :                 _maxSubmissionCost,
-     285                 :            :                 tokenTotalFeeAmount,
-     286                 :            :                 res
-     287                 :            :             );
-     288                 :            :         }
-     289                 :          4 :         emit DepositInitiated(_l1Token, _from, _to, seqNum, _amount);
-     290                 :          4 :         return abi.encode(seqNum);
-     291                 :            :     }
-     292                 :            : 
-     293                 :            :     function outboundEscrowTransfer(
-     294                 :            :         address _l1Token,
-     295                 :            :         address _from,
-     296                 :            :         uint256 _amount
-     297                 :            :     ) internal virtual returns (uint256 amountReceived) {
-     298                 :            :         // this method is virtual since different subclasses can handle escrow differently
-     299                 :            :         // user funds are escrowed on the gateway using this function
-     300                 :          6 :         uint256 prevBalance = IERC20(_l1Token).balanceOf(address(this));
-     301                 :          6 :         IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);
-     302                 :          4 :         uint256 postBalance = IERC20(_l1Token).balanceOf(address(this));
-     303                 :          4 :         return postBalance - prevBalance;
-     304                 :            :     }
-     305                 :            : 
-     306                 :            :     function getOutboundCalldata(
-     307                 :            :         address _l1Token,
-     308                 :            :         address _from,
-     309                 :            :         address _to,
-     310                 :            :         uint256 _amount,
-     311                 :            :         bytes memory _data
-     312                 :            :     ) public view virtual override returns (bytes memory outboundCalldata) {
-     313                 :            :         // this function is public so users can query how much calldata will be sent to the L2
-     314                 :            :         // before execution
-     315                 :            :         // it is virtual since different gateway subclasses can build this calldata differently
-     316                 :            :         // ( ie the standard ERC20 gateway queries for a tokens name/symbol/decimals )
-     317                 :          0 :         bytes memory emptyBytes = "";
-     318                 :            : 
-     319                 :          0 :         outboundCalldata = abi.encodeWithSelector(
-     320                 :            :             ITokenGateway.finalizeInboundTransfer.selector,
-     321                 :            :             _l1Token,
-     322                 :            :             _from,
-     323                 :            :             _to,
-     324                 :            :             _amount,
-     325                 :            :             GatewayMessageHandler.encodeToL2GatewayMsg(emptyBytes, _data)
-     326                 :            :         );
-     327                 :            : 
-     328                 :          0 :         return outboundCalldata;
-     329                 :            :     }
-     330                 :            : 
-     331                 :            :     function supportsInterface(bytes4 interfaceId)
-     332                 :            :         public
-     333                 :            :         view
-     334                 :            :         virtual
-     335                 :            :         override(ERC165, IERC165)
-     336                 :            :         returns (bool)
-     337                 :            :     {
-     338                 :            :         // registering interfaces that is added after arb-bridge-peripherals >1.0.11
-     339                 :            :         // using function selector instead of single function interfaces to reduce bloat
-     340                 :        512 :         return
-     341                 :            :             interfaceId == this.outboundTransferCustomRefund.selector ||
-     342                 :            :             super.supportsInterface(interfaceId);
-     343                 :            :     }
-     344                 :            : 
-     345                 :            :     /**
-     346                 :            :      * @notice Parse data that was encoded by user and passed into the outbound TX entrypoint
-     347                 :            :      * @dev In case of standard ETH-based rollup, format of encoded data is expected to be:
-     348                 :            :      *      - maxSubmissionCost (uint256)
-     349                 :            :      *      - callHookData (bytes)
-     350                 :            :      *      In case of ERC20-based rollup, format of encoded data is expected to be:
-     351                 :            :      *      - maxSubmissionCost (uint256)
-     352                 :            :      *      - tokenTotalFeeAmount (uint256)
-     353                 :            :      *      - callHookData (bytes)
-     354                 :            :      * @param data data encoded by user
-     355                 :            :      * @return maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
-     356                 :            :      * @return callHookData Calldata for extra call in inboundEscrowAndCall on L2
-     357                 :            :      * @return tokenTotalFeeAmount Amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups, otherwise 0)
-     358                 :            :      */
-     359                 :            :     function _parseUserEncodedData(
-     360                 :            :         bytes memory data
-     361                 :            :     )
-     362                 :            :         internal
-     363                 :            :         pure
-     364                 :            :         virtual
-     365                 :            :         returns (uint256 maxSubmissionCost, bytes memory callHookData, uint256 tokenTotalFeeAmount)
-     366                 :            :     {
-     367                 :          5 :         (maxSubmissionCost, callHookData) = abi.decode(data, (uint256, bytes));
-     368                 :            :     }
-     369                 :            : 
-     370                 :            :     /**
-     371                 :            :      * @notice Intermediate internal function that passes on parameters needed to trigger creation of retryable ticket.
-     372                 :            :      * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2
-     373                 :            :      * @param _from Initiator of deposit
-     374                 :            :      * @param _amount Token of token being deposited
-     375                 :            :      * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution
-     376                 :            :      * @param _gasPriceBid Gas price for L2 execution
-     377                 :            :      * @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
-     378                 :            :      * //param tokenTotalFeeAmount Amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups)
-     379                 :            :      * @param _data encoded data from router and user
-     380                 :            :      * @return res abi encoded inbox sequence number
-     381                 :            :      */
-     382                 :            :     function _initiateDeposit(
-     383                 :            :         address _refundTo,
-     384                 :            :         address _from,
-     385                 :            :         uint256 _amount,
-     386                 :            :         uint256 _maxGas,
-     387                 :            :         uint256 _gasPriceBid,
-     388                 :            :         uint256 _maxSubmissionCost,
-     389                 :            :         uint256, // tokenTotalFeeAmount
-     390                 :            :         bytes memory _data
-     391                 :            :     ) internal virtual returns (uint256) {
-     392                 :          2 :         return
-     393                 :            :             createOutboundTxCustomRefund(
-     394                 :            :                 _refundTo,
-     395                 :            :                 _from,
-     396                 :            :                 _amount,
-     397                 :            :                 _maxGas,
-     398                 :            :                 _gasPriceBid,
-     399                 :            :                 _maxSubmissionCost,
-     400                 :            :                 _data
-     401                 :            :             );
-     402                 :            :     }
-     403                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1CustomGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1CustomGateway.sol.func-sort-c.html deleted file mode 100644 index b942e63372..0000000000 --- a/coverage/ethereum/gateway/L1CustomGateway.sol.func-sort-c.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1CustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:162857.1 %
Date:2023-04-27 16:26:32Functions:3742.9 %
Branches:11010.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1CustomGateway.finalizeInboundTransfer0
L1CustomGateway.forceRegisterTokenToL20
L1CustomGateway.outboundTransferCustomRefund0
L1CustomGateway.setOwner0
L1CustomGateway.initialize6
L1CustomGateway.registerTokenToL26
L1CustomGateway.calculateL2TokenAddress7
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1CustomGateway.sol.func.html b/coverage/ethereum/gateway/L1CustomGateway.sol.func.html deleted file mode 100644 index fe33feb218..0000000000 --- a/coverage/ethereum/gateway/L1CustomGateway.sol.func.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1CustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:162857.1 %
Date:2023-04-27 16:26:32Functions:3742.9 %
Branches:11010.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1CustomGateway.calculateL2TokenAddress7
L1CustomGateway.finalizeInboundTransfer0
L1CustomGateway.forceRegisterTokenToL20
L1CustomGateway.initialize6
L1CustomGateway.outboundTransferCustomRefund0
L1CustomGateway.registerTokenToL26
L1CustomGateway.setOwner0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1CustomGateway.sol.gcov.html b/coverage/ethereum/gateway/L1CustomGateway.sol.gcov.html deleted file mode 100644 index d150f0f873..0000000000 --- a/coverage/ethereum/gateway/L1CustomGateway.sol.gcov.html +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1CustomGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1CustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:162857.1 %
Date:2023-04-27 16:26:32Functions:3742.9 %
Branches:11010.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import { ArbitrumEnabledToken } from "../ICustomToken.sol";
-      22                 :            : import "./L1ArbitrumExtendedGateway.sol";
-      23                 :            : import "../../arbitrum/gateway/L2CustomGateway.sol";
-      24                 :            : import "../../libraries/gateway/ICustomGateway.sol";
-      25                 :            : import "@openzeppelin/contracts/utils/Address.sol";
-      26                 :            : 
-      27                 :            : import "../../libraries/Whitelist.sol";
-      28                 :            : 
-      29                 :            : /**
-      30                 :            :  * @title Gatway for "custom" bridging functionality
-      31                 :            :  * @notice Handles some (but not all!) custom Gateway needs.
-      32                 :            :  */
-      33                 :            : contract L1CustomGateway is L1ArbitrumExtendedGateway, ICustomGateway {
-      34                 :            :     using Address for address;
-      35                 :            :     // stores addresses of L2 tokens to be used
-      36                 :            :     mapping(address => address) public override l1ToL2Token;
-      37                 :            :     // owner is able to force add custom mappings
-      38                 :            :     address public owner;
-      39                 :            : 
-      40                 :            :     // whitelist not used anymore
-      41                 :            :     address public whitelist;
-      42                 :            : 
-      43                 :            :     // start of inline reentrancy guard
-      44                 :            :     // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.2/contracts/utils/ReentrancyGuard.sol
-      45                 :            :     uint256 private constant _NOT_ENTERED = 1;
-      46                 :            :     uint256 private constant _ENTERED = 2;
-      47                 :            :     uint256 private _status;
-      48                 :            : 
-      49                 :            :     modifier nonReentrant() {
-      50                 :            :         // On the first call to nonReentrant, _notEntered will be true
-      51                 :            :         require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
-      52                 :            :         // Any calls to nonReentrant after this point will fail
-      53                 :            :         _status = _ENTERED;
-      54                 :            :         _;
-      55                 :            :         _status = _NOT_ENTERED;
-      56                 :            :     }
-      57                 :            : 
-      58                 :            :     modifier onlyOwner() {
-      59                 :            :         require(msg.sender == owner, "ONLY_OWNER");
-      60                 :            :         _;
-      61                 :            :     }
-      62                 :            : 
-      63                 :            :     function outboundTransferCustomRefund(
-      64                 :            :         address _l1Token,
-      65                 :            :         address _refundTo,
-      66                 :            :         address _to,
-      67                 :            :         uint256 _amount,
-      68                 :            :         uint256 _maxGas,
-      69                 :            :         uint256 _gasPriceBid,
-      70                 :            :         bytes calldata _data
-      71                 :            :     ) public payable override nonReentrant returns (bytes memory res) {
-      72                 :          0 :         return
-      73                 :            :             super.outboundTransferCustomRefund(
-      74                 :            :                 _l1Token,
-      75                 :            :                 _refundTo,
-      76                 :            :                 _to,
-      77                 :            :                 _amount,
-      78                 :            :                 _maxGas,
-      79                 :            :                 _gasPriceBid,
-      80                 :            :                 _data
-      81                 :            :             );
-      82                 :            :     }
-      83                 :            : 
-      84                 :            :     function finalizeInboundTransfer(
-      85                 :            :         address _token,
-      86                 :            :         address _from,
-      87                 :            :         address _to,
-      88                 :            :         uint256 _amount,
-      89                 :            :         bytes calldata _data
-      90                 :            :     ) public payable override nonReentrant {
-      91                 :            :         // the superclass checks onlyCounterpartGateway
-      92                 :          0 :         super.finalizeInboundTransfer(_token, _from, _to, _amount, _data);
-      93                 :            :     }
-      94                 :            : 
-      95                 :            :     function initialize(
-      96                 :            :         address _l1Counterpart,
-      97                 :            :         address _l1Router,
-      98                 :            :         address _inbox,
-      99                 :            :         address _owner
-     100                 :            :     ) public {
-     101                 :          6 :         L1ArbitrumGateway._initialize(_l1Counterpart, _l1Router, _inbox);
-     102                 :          6 :         owner = _owner;
-     103                 :            :         // disable whitelist by default
-     104                 :          6 :         whitelist = address(0);
-     105                 :            :         // reentrancy guard
-     106                 :          6 :         _status = _NOT_ENTERED;
-     107                 :            :     }
-     108                 :            : 
-     109                 :            :     /**
-     110                 :            :      * @notice Calculate the address used when bridging an ERC20 token
-     111                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
-     112                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
-     113                 :            :      * @param l1ERC20 address of L1 token
-     114                 :            :      * @return L2 address of a bridged ERC20 token
-     115                 :            :      */
-     116                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override(ITokenGateway, TokenGateway) returns (address) {
-     117                 :          7 :         return l1ToL2Token[l1ERC20];
-     118                 :            :     }
-     119                 :            : 
-     120                 :            :     /**
-     121                 :            :      * @notice Allows L1 Token contract to trustlessly register its custom L2 counterpart. (other registerTokenToL2 method allows excess eth recovery from _maxSubmissionCost and is recommended)
-     122                 :            :      * @param _l2Address counterpart address of L1 token
-     123                 :            :      * @param _maxGas max gas for L2 retryable exrecution
-     124                 :            :      * @param _gasPriceBid gas price for L2 retryable ticket
-     125                 :            :      * @param  _maxSubmissionCost base submission cost  L2 retryable tick3et
-     126                 :            :      * @return Retryable ticket ID
-     127                 :            :      */
-     128                 :            :     function registerTokenToL2(
-     129                 :            :         address _l2Address,
-     130                 :            :         uint256 _maxGas,
-     131                 :            :         uint256 _gasPriceBid,
-     132                 :            :         uint256 _maxSubmissionCost
-     133                 :            :     ) external payable returns (uint256) {
-     134                 :          0 :         return registerTokenToL2(_l2Address, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender);
-     135                 :            :     }
-     136                 :            : 
-     137                 :            :     /**
-     138                 :            :      * @notice Allows L1 Token contract to trustlessly register its custom L2 counterpart.
-     139                 :            :      * param _l2Address counterpart address of L1 token
-     140                 :            :      * param _maxGas max gas for L2 retryable exrecution
-     141                 :            :      * param _gasPriceBid gas price for L2 retryable ticket
-     142                 :            :      * param  _maxSubmissionCost base submission cost  L2 retryable tick3et
-     143                 :            :      * param _creditBackAddress address for crediting back overpayment of _maxSubmissionCost
-     144                 :            :      * return Retryable ticket ID
-     145                 :            :      */
-     146                 :            :     function registerTokenToL2(
-     147                 :            :         address _l2Address,
-     148                 :            :         uint256 _maxGas,
-     149                 :            :         uint256 _gasPriceBid,
-     150                 :            :         uint256 _maxSubmissionCost,
-     151                 :            :         address _creditBackAddress
-     152                 :            :     ) public payable virtual returns (uint256) {
-     153         [ #  + ]:          6 :         require(
-     154                 :            :             ArbitrumEnabledToken(msg.sender).isArbitrumEnabled() == uint8(0xb1),
-     155                 :            :             "NOT_ARB_ENABLED"
-     156                 :            :         );
-     157                 :            : 
-     158                 :          6 :         address currL2Addr = l1ToL2Token[msg.sender];
-     159         [ #  # ]:          6 :         if (currL2Addr != address(0)) {
-     160                 :            :             // if token is already set, don't allow it to set a different L2 address
-     161         [ #  # ]:          0 :             require(currL2Addr == _l2Address, "NO_UPDATE_TO_DIFFERENT_ADDR");
-     162                 :            :         }
-     163                 :            : 
-     164                 :          6 :         l1ToL2Token[msg.sender] = _l2Address;
-     165                 :            : 
-     166                 :          6 :         address[] memory l1Addresses = new address[](1);
-     167                 :          6 :         address[] memory l2Addresses = new address[](1);
-     168                 :          6 :         l1Addresses[0] = msg.sender;
-     169                 :          6 :         l2Addresses[0] = _l2Address;
-     170                 :            : 
-     171                 :          6 :         emit TokenSet(l1Addresses[0], l2Addresses[0]);
-     172                 :            : 
-     173                 :          6 :         bytes memory _data = abi.encodeWithSelector(
-     174                 :            :             L2CustomGateway.registerTokenFromL1.selector,
-     175                 :            :             l1Addresses,
-     176                 :            :             l2Addresses
-     177                 :            :         );
-     178                 :            : 
-     179                 :          6 :         return
-     180                 :            :             sendTxToL2(
-     181                 :            :                 inbox,
-     182                 :            :                 counterpartGateway,
-     183                 :            :                 _creditBackAddress,
-     184                 :            :                 msg.value,
-     185                 :            :                 0,
-     186                 :            :                 _maxSubmissionCost,
-     187                 :            :                 _maxGas,
-     188                 :            :                 _gasPriceBid,
-     189                 :            :                 _data
-     190                 :            :             );
-     191                 :            :     }
-     192                 :            : 
-     193                 :            :     function setOwner(address newOwner) external onlyOwner {
-     194         [ #  # ]:          0 :         require(newOwner != address(0), "INVALID_OWNER");
-     195                 :          0 :         owner = newOwner;
-     196                 :            :     }
-     197                 :            : 
-     198                 :            :     /**
-     199                 :            :      * @notice Allows owner to force register a custom L1/L2 token pair.
-     200                 :            :      * @dev _l1Addresses[i] counterpart is assumed to be _l2Addresses[i]
-     201                 :            :      * @param _l1Addresses array of L1 addresses
-     202                 :            :      * @param _l2Addresses array of L2 addresses
-     203                 :            :      * @param _maxGas max gas for L2 retryable exrecution
-     204                 :            :      * @param _gasPriceBid gas price for L2 retryable ticket
-     205                 :            :      * @param  _maxSubmissionCost base submission cost  L2 retryable tick3et
-     206                 :            :      * @return Retryable ticket ID
-     207                 :            :      */
-     208                 :            :     function forceRegisterTokenToL2(
-     209                 :            :         address[] calldata _l1Addresses,
-     210                 :            :         address[] calldata _l2Addresses,
-     211                 :            :         uint256 _maxGas,
-     212                 :            :         uint256 _gasPriceBid,
-     213                 :            :         uint256 _maxSubmissionCost
-     214                 :            :     ) external payable onlyOwner returns (uint256) {
-     215         [ #  # ]:          0 :         require(_l1Addresses.length == _l2Addresses.length, "INVALID_LENGTHS");
-     216                 :            : 
-     217                 :          0 :         for (uint256 i = 0; i < _l1Addresses.length; i++) {
-     218                 :            :             // here we assume the owner checked both addresses offchain before force registering
-     219                 :            :             // require(address(_l1Addresses[i]).isContract(), "MUST_BE_CONTRACT");
-     220                 :          0 :             l1ToL2Token[_l1Addresses[i]] = _l2Addresses[i];
-     221                 :          0 :             emit TokenSet(_l1Addresses[i], _l2Addresses[i]);
-     222                 :            :         }
-     223                 :            : 
-     224                 :          0 :         bytes memory _data = abi.encodeWithSelector(
-     225                 :            :             L2CustomGateway.registerTokenFromL1.selector,
-     226                 :            :             _l1Addresses,
-     227                 :            :             _l2Addresses
-     228                 :            :         );
-     229                 :            : 
-     230                 :          0 :         return
-     231                 :            :             sendTxToL2(
-     232                 :            :                 inbox,
-     233                 :            :                 counterpartGateway,
-     234                 :            :                 msg.sender,
-     235                 :            :                 msg.value,
-     236                 :            :                 0,
-     237                 :            :                 _maxSubmissionCost,
-     238                 :            :                 _maxGas,
-     239                 :            :                 _gasPriceBid,
-     240                 :            :                 _data
-     241                 :            :             );
-     242                 :            :     }
-     243                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ERC20Gateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ERC20Gateway.sol.func-sort-c.html deleted file mode 100644 index 6fc20e1578..0000000000 --- a/coverage/ethereum/gateway/L1ERC20Gateway.sol.func-sort-c.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ERC20Gateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1818100.0 %
Date:2023-04-27 16:26:32Functions:77100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ERC20Gateway.finalizeInboundTransfer6
L1ERC20Gateway.getOutboundCalldata6
L1ERC20Gateway.initialize7
L1ERC20Gateway.outboundTransferCustomRefund10
L1ERC20Gateway.callStatic30
L1ERC20Gateway.calculateL2TokenAddress512
L1ERC20Gateway.getSalt518
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ERC20Gateway.sol.func.html b/coverage/ethereum/gateway/L1ERC20Gateway.sol.func.html deleted file mode 100644 index 9853a7120a..0000000000 --- a/coverage/ethereum/gateway/L1ERC20Gateway.sol.func.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ERC20Gateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1818100.0 %
Date:2023-04-27 16:26:32Functions:77100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ERC20Gateway.calculateL2TokenAddress512
L1ERC20Gateway.callStatic30
L1ERC20Gateway.finalizeInboundTransfer6
L1ERC20Gateway.getOutboundCalldata6
L1ERC20Gateway.getSalt518
L1ERC20Gateway.initialize7
L1ERC20Gateway.outboundTransferCustomRefund10
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ERC20Gateway.sol.gcov.html b/coverage/ethereum/gateway/L1ERC20Gateway.sol.gcov.html deleted file mode 100644 index c9ddaff34e..0000000000 --- a/coverage/ethereum/gateway/L1ERC20Gateway.sol.gcov.html +++ /dev/null @@ -1,246 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ERC20Gateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:1818100.0 %
Date:2023-04-27 16:26:32Functions:77100.0 %
Branches:44100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./L1ArbitrumExtendedGateway.sol";
-      22                 :            : import "@openzeppelin/contracts/utils/Create2.sol";
-      23                 :            : import "../../libraries/Whitelist.sol";
-      24                 :            : 
-      25                 :            : /**
-      26                 :            :  * @title Layer 1 Gateway contract for bridging standard ERC20s
-      27                 :            :  * @notice This contract handles token deposits, holds the escrowed tokens on layer 1, and (ultimately) finalizes withdrawals.
-      28                 :            :  * @dev Any ERC20 that requires non-standard functionality should use a separate gateway.
-      29                 :            :  * Messages to layer 2 use the inbox's createRetryableTicket method.
-      30                 :            :  */
-      31                 :            : contract L1ERC20Gateway is L1ArbitrumExtendedGateway {
-      32                 :            :     // used for create2 address calculation
-      33                 :            :     bytes32 public cloneableProxyHash;
-      34                 :            :     // We don't use the solidity creationCode as it breaks when upgrading contracts
-      35                 :            :     // keccak256(type(ClonableBeaconProxy).creationCode);
-      36                 :            :     address public l2BeaconProxyFactory;
-      37                 :            :     // whitelist not used anymore
-      38                 :            :     address public whitelist;
-      39                 :            : 
-      40                 :            :     // start of inline reentrancy guard
-      41                 :            :     // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.2/contracts/utils/ReentrancyGuard.sol
-      42                 :            :     uint256 private constant _NOT_ENTERED = 1;
-      43                 :            :     uint256 private constant _ENTERED = 2;
-      44                 :            :     uint256 private _status;
-      45                 :            : 
-      46                 :            :     modifier nonReentrant() {
-      47                 :            :         // On the first call to nonReentrant, _notEntered will be true
-      48                 :            :         require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
-      49                 :            :         // Any calls to nonReentrant after this point will fail
-      50                 :            :         _status = _ENTERED;
-      51                 :            :         _;
-      52                 :            :         _status = _NOT_ENTERED;
-      53                 :            :     }
-      54                 :            : 
-      55                 :            :     // end of inline reentrancy guard
-      56                 :            : 
-      57                 :            :     function outboundTransferCustomRefund(
-      58                 :            :         address _l1Token,
-      59                 :            :         address _refundTo,
-      60                 :            :         address _to,
-      61                 :            :         uint256 _amount,
-      62                 :            :         uint256 _maxGas,
-      63                 :            :         uint256 _gasPriceBid,
-      64                 :            :         bytes calldata _data
-      65                 :            :     ) public payable override nonReentrant returns (bytes memory res) {
-      66                 :         12 :         return
-      67                 :            :             super.outboundTransferCustomRefund(
-      68                 :            :                 _l1Token,
-      69                 :            :                 _refundTo,
-      70                 :            :                 _to,
-      71                 :            :                 _amount,
-      72                 :            :                 _maxGas,
-      73                 :            :                 _gasPriceBid,
-      74                 :            :                 _data
-      75                 :            :             );
-      76                 :            :     }
-      77                 :            : 
-      78                 :            :     function finalizeInboundTransfer(
-      79                 :            :         address _token,
-      80                 :            :         address _from,
-      81                 :            :         address _to,
-      82                 :            :         uint256 _amount,
-      83                 :            :         bytes calldata _data
-      84                 :            :     ) public payable override nonReentrant {
-      85                 :            :         // the superclass checks onlyCounterpartGateway
-      86                 :          6 :         super.finalizeInboundTransfer(_token, _from, _to, _amount, _data);
-      87                 :            :     }
-      88                 :            : 
-      89                 :            :     function initialize(
-      90                 :            :         address _l2Counterpart,
-      91                 :            :         address _router,
-      92                 :            :         address _inbox,
-      93                 :            :         bytes32 _cloneableProxyHash,
-      94                 :            :         address _l2BeaconProxyFactory
-      95                 :            :     ) public {
-      96                 :          7 :         L1ArbitrumGateway._initialize(_l2Counterpart, _router, _inbox);
-      97         [ +  + ]:          7 :         require(_cloneableProxyHash != bytes32(0), "INVALID_PROXYHASH");
-      98         [ +  + ]:          5 :         require(_l2BeaconProxyFactory != address(0), "INVALID_BEACON");
-      99                 :          3 :         cloneableProxyHash = _cloneableProxyHash;
-     100                 :          3 :         l2BeaconProxyFactory = _l2BeaconProxyFactory;
-     101                 :            :         // disable whitelist by default
-     102                 :          3 :         whitelist = address(0);
-     103                 :            :         // reentrancy guard
-     104                 :          3 :         _status = _NOT_ENTERED;
-     105                 :            :     }
-     106                 :            : 
-     107                 :            :     /**
-     108                 :            :      * @notice utility function used to perform external read-only calls.
-     109                 :            :      * @dev the result is returned even if the call failed or was directed at an EOA,
-     110                 :            :      * it is cheaper to have the L2 consumer identify and deal with this.
-     111                 :            :      * @return result bytes, even if the call failed.
-     112                 :            :      */
-     113                 :            :     function callStatic(address targetContract, bytes4 targetFunction)
-     114                 :            :         internal
-     115                 :            :         view
-     116                 :            :         returns (bytes memory)
-     117                 :            :     {
-     118                 :         30 :         (
-     119                 :            :             ,
-     120                 :            :             /* bool success */
-     121                 :            :             bytes memory res
-     122                 :         30 :         ) = targetContract.staticcall(abi.encodeWithSelector(targetFunction));
-     123                 :         30 :         return res;
-     124                 :            :     }
-     125                 :            : 
-     126                 :            :     function getOutboundCalldata(
-     127                 :            :         address _token,
-     128                 :            :         address _from,
-     129                 :            :         address _to,
-     130                 :            :         uint256 _amount,
-     131                 :            :         bytes memory _data
-     132                 :            :     ) public view override returns (bytes memory outboundCalldata) {
-     133                 :            :         // TODO: cheaper to make static calls or save isDeployed to storage?
-     134                 :         10 :         bytes memory deployData = abi.encode(
-     135                 :            :             callStatic(_token, ERC20.name.selector),
-     136                 :            :             callStatic(_token, ERC20.symbol.selector),
-     137                 :            :             callStatic(_token, ERC20.decimals.selector)
-     138                 :            :         );
-     139                 :            : 
-     140                 :         10 :         outboundCalldata = abi.encodeWithSelector(
-     141                 :            :             ITokenGateway.finalizeInboundTransfer.selector,
-     142                 :            :             _token,
-     143                 :            :             _from,
-     144                 :            :             _to,
-     145                 :            :             _amount,
-     146                 :            :             GatewayMessageHandler.encodeToL2GatewayMsg(deployData, _data)
-     147                 :            :         );
-     148                 :            : 
-     149                 :         10 :         return outboundCalldata;
-     150                 :            :     }
-     151                 :            : 
-     152                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override(ITokenGateway, TokenGateway) returns (address) {
-     153                 :        518 :         bytes32 salt = getSalt(l1ERC20);
-     154                 :        518 :         return Create2.computeAddress(salt, cloneableProxyHash, l2BeaconProxyFactory);
-     155                 :            :     }
-     156                 :            : 
-     157                 :            :     function getSalt(address l1ERC20) internal view returns (bytes32) {
-     158                 :            :         // TODO: use a library
-     159                 :        518 :         return keccak256(abi.encode(counterpartGateway, keccak256(abi.encode(l1ERC20))));
-     160                 :            :     }
-     161                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func-sort-c.html deleted file mode 100644 index 8a5c1e448b..0000000000 --- a/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ForceOnlyReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ForceOnlyReverseCustomGateway.registerTokenToL20
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func.html b/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func.html deleted file mode 100644 index 25927b966f..0000000000 --- a/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ForceOnlyReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ForceOnlyReverseCustomGateway.registerTokenToL20
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.gcov.html b/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.gcov.html deleted file mode 100644 index f6d97d254c..0000000000 --- a/coverage/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol.gcov.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ForceOnlyReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./L1ReverseCustomGateway.sol";
-      22                 :            : 
-      23                 :            : /**
-      24                 :            :  * @title An L1 Reverse gateway which only allows force registration
-      25                 :            :  */
-      26                 :            : contract L1ForceOnlyReverseCustomGateway is L1ReverseCustomGateway {
-      27                 :            :     function registerTokenToL2(
-      28                 :            :         address _l2Address,
-      29                 :            :         uint256 _maxGas,
-      30                 :            :         uint256 _gasPriceBid,
-      31                 :            :         uint256 _maxSubmissionCost,
-      32                 :            :         address _creditBackAddress
-      33                 :            :     ) public payable virtual override returns (uint256) {
-      34                 :          0 :         revert("REGISTER_TOKEN_ON_L2_DISABLED");
-      35                 :            :     }
-      36                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1GatewayRouter.sol.func-sort-c.html b/coverage/ethereum/gateway/L1GatewayRouter.sol.func-sort-c.html deleted file mode 100644 index 1e0179e586..0000000000 --- a/coverage/ethereum/gateway/L1GatewayRouter.sol.func-sort-c.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1GatewayRouter.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:354087.5 %
Date:2023-04-27 16:26:32Functions:7977.8 %
Branches:131872.2 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1GatewayRouter.outboundTransfer0
L1GatewayRouter.outboundTransferCustomRefund0
L1GatewayRouter.setDefaultGateway1
L1GatewayRouter.setGateways3
L1GatewayRouter.initialize4
L1GatewayRouter._setGateways7
L1GatewayRouter.setGateway8
L1GatewayRouter.supportsInterface256
L1GatewayRouter.setOwner258
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1GatewayRouter.sol.func.html b/coverage/ethereum/gateway/L1GatewayRouter.sol.func.html deleted file mode 100644 index a73094c070..0000000000 --- a/coverage/ethereum/gateway/L1GatewayRouter.sol.func.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1GatewayRouter.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:354087.5 %
Date:2023-04-27 16:26:32Functions:7977.8 %
Branches:131872.2 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1GatewayRouter._setGateways7
L1GatewayRouter.initialize4
L1GatewayRouter.outboundTransfer0
L1GatewayRouter.outboundTransferCustomRefund0
L1GatewayRouter.setDefaultGateway1
L1GatewayRouter.setGateway8
L1GatewayRouter.setGateways3
L1GatewayRouter.setOwner258
L1GatewayRouter.supportsInterface256
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1GatewayRouter.sol.gcov.html b/coverage/ethereum/gateway/L1GatewayRouter.sol.gcov.html deleted file mode 100644 index 576473a750..0000000000 --- a/coverage/ethereum/gateway/L1GatewayRouter.sol.gcov.html +++ /dev/null @@ -1,391 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1GatewayRouter.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:354087.5 %
Date:2023-04-27 16:26:32Functions:7977.8 %
Branches:131872.2 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../../libraries/Whitelist.sol";
-      22                 :            : 
-      23                 :            : import { ArbitrumEnabledToken } from "../ICustomToken.sol";
-      24                 :            : import "../L1ArbitrumMessenger.sol";
-      25                 :            : import "../../libraries/gateway/GatewayRouter.sol";
-      26                 :            : import "../../arbitrum/gateway/L2GatewayRouter.sol";
-      27                 :            : import "../../libraries/ERC165.sol";
-      28                 :            : import "./IL1GatewayRouter.sol";
-      29                 :            : import "./IL1ArbitrumGateway.sol";
-      30                 :            : 
-      31                 :            : /**
-      32                 :            :  * @title Handles deposits from Erhereum into Arbitrum. Tokens are routered to their appropriate L1 gateway (Router itself also conforms to the Gateway itnerface).
-      33                 :            :  * @notice Router also serves as an L1-L2 token address oracle.
-      34                 :            :  */
-      35                 :            : contract L1GatewayRouter is
-      36                 :            :     WhitelistConsumer,
-      37                 :            :     L1ArbitrumMessenger,
-      38                 :            :     GatewayRouter,
-      39                 :            :     ERC165,
-      40                 :            :     IL1GatewayRouter
-      41                 :            : {
-      42                 :            :     address public override owner;
-      43                 :            :     address public override inbox;
-      44                 :            : 
-      45                 :            :     modifier onlyOwner() {
-      46                 :            :         require(msg.sender == owner, "ONLY_OWNER");
-      47                 :            :         _;
-      48                 :            :     }
-      49                 :            : 
-      50                 :            :     function initialize(
-      51                 :            :         address _owner,
-      52                 :            :         address _defaultGateway,
-      53                 :            :         address, // was _whitelist, now unused
-      54                 :            :         address _counterpartGateway,
-      55                 :            :         address _inbox
-      56                 :            :     ) public {
-      57                 :          4 :         GatewayRouter._initialize(_counterpartGateway, address(0), _defaultGateway);
-      58                 :          2 :         owner = _owner;
-      59                 :          2 :         WhitelistConsumer.whitelist = address(0);
-      60                 :          2 :         inbox = _inbox;
-      61                 :            :     }
-      62                 :            : 
-      63                 :            :     function setDefaultGateway(
-      64                 :            :         address newL1DefaultGateway,
-      65                 :            :         uint256 _maxGas,
-      66                 :            :         uint256 _gasPriceBid,
-      67                 :            :         uint256 _maxSubmissionCost
-      68                 :            :     ) external payable onlyOwner returns (uint256) {
-      69                 :          1 :         defaultGateway = newL1DefaultGateway;
-      70                 :            : 
-      71                 :          1 :         emit DefaultGatewayUpdated(newL1DefaultGateway);
-      72                 :            : 
-      73                 :          1 :         address l2NewDefaultGateway;
-      74                 :            : 
-      75         [ #  + ]:          1 :         if (newL1DefaultGateway != address(0)) {
-      76                 :          1 :             l2NewDefaultGateway = TokenGateway(newL1DefaultGateway).counterpartGateway();
-      77                 :            :         }
-      78                 :            : 
-      79                 :          1 :         bytes memory data = abi.encodeWithSelector(
-      80                 :            :             L2GatewayRouter.setDefaultGateway.selector,
-      81                 :            :             l2NewDefaultGateway
-      82                 :            :         );
-      83                 :            : 
-      84                 :          1 :         return
-      85                 :            :             sendTxToL2(
-      86                 :            :                 inbox,
-      87                 :            :                 counterpartGateway,
-      88                 :            :                 msg.sender,
-      89                 :            :                 msg.value,
-      90                 :            :                 0,
-      91                 :            :                 L2GasParams({
-      92                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
-      93                 :            :                     _maxGas: _maxGas,
-      94                 :            :                     _gasPriceBid: _gasPriceBid
-      95                 :            :                 }),
-      96                 :            :                 data
-      97                 :            :             );
-      98                 :            :     }
-      99                 :            : 
-     100                 :            :     function setOwner(address newOwner) external onlyOwner {
-     101         [ +  + ]:        257 :         require(newOwner != address(0), "INVALID_OWNER");
-     102                 :            :         // set newOwner to address(1) to disable owner and keep `initialize` safe
-     103                 :        256 :         owner = newOwner;
-     104                 :            :     }
-     105                 :            : 
-     106                 :            :     function _setGateways(
-     107                 :            :         address[] memory _token,
-     108                 :            :         address[] memory _gateway,
-     109                 :            :         uint256 _maxGas,
-     110                 :            :         uint256 _gasPriceBid,
-     111                 :            :         uint256 _maxSubmissionCost,
-     112                 :            :         address _creditBackAddress
-     113                 :            :     ) internal returns (uint256) {
-     114         [ #  + ]:          7 :         require(_token.length == _gateway.length, "WRONG_LENGTH");
-     115                 :            : 
-     116                 :          7 :         for (uint256 i = 0; i < _token.length; i++) {
-     117                 :          8 :             l1TokenToGateway[_token[i]] = _gateway[i];
-     118                 :          8 :             emit GatewaySet(_token[i], _gateway[i]);
-     119                 :            :             // overwrite memory so the L2 router receives the L2 address of each gateway
-     120         [ #  + ]:          8 :             if (_gateway[i] != address(0) && _gateway[i] != DISABLED) {
-     121                 :            :                 // if we are assigning a gateway to the token, the address oracle of the gateway
-     122                 :            :                 // must return something other than the 0 address
-     123                 :            :                 // this check helps avoid misconfiguring gateways
-     124         [ +  + ]:          7 :                 require(
-     125                 :            :                     TokenGateway(_gateway[i]).calculateL2TokenAddress(_token[i]) != address(0),
-     126                 :            :                     "TOKEN_NOT_HANDLED_BY_GATEWAY"
-     127                 :            :                 );
-     128                 :          6 :                 _gateway[i] = TokenGateway(_gateway[i]).counterpartGateway();
-     129                 :            :             }
-     130                 :            :         }
-     131                 :            : 
-     132                 :          6 :         bytes memory data = abi.encodeWithSelector(
-     133                 :            :             L2GatewayRouter.setGateway.selector,
-     134                 :            :             _token,
-     135                 :            :             _gateway
-     136                 :            :         );
-     137                 :            : 
-     138                 :          6 :         return
-     139                 :            :             sendTxToL2(
-     140                 :            :                 inbox,
-     141                 :            :                 counterpartGateway,
-     142                 :            :                 _creditBackAddress,
-     143                 :            :                 msg.value,
-     144                 :            :                 0,
-     145                 :            :                 L2GasParams({
-     146                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
-     147                 :            :                     _maxGas: _maxGas,
-     148                 :            :                     _gasPriceBid: _gasPriceBid
-     149                 :            :                 }),
-     150                 :            :                 data
-     151                 :            :             );
-     152                 :            :     }
-     153                 :            : 
-     154                 :            :     /**
-     155                 :            :      * @notice Allows L1 Token contract to trustlessly register its gateway. (other setGateway method allows excess eth recovery from _maxSubmissionCost and is recommended)
-     156                 :            :      * @param _gateway l1 gateway address
-     157                 :            :      * @param _maxGas max gas for L2 retryable exrecution
-     158                 :            :      * @param _gasPriceBid gas price for L2 retryable ticket
-     159                 :            :      * @param  _maxSubmissionCost base submission cost  L2 retryable tick3et
-     160                 :            :      * @return Retryable ticket ID
-     161                 :            :      */
-     162                 :            :     function setGateway(
-     163                 :            :         address _gateway,
-     164                 :            :         uint256 _maxGas,
-     165                 :            :         uint256 _gasPriceBid,
-     166                 :            :         uint256 _maxSubmissionCost
-     167                 :            :     ) external payable override returns (uint256) {
-     168                 :          1 :         return setGateway(_gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender);
-     169                 :            :     }
-     170                 :            : 
-     171                 :            :     /**
-     172                 :            :      * @notice Allows L1 Token contract to trustlessly register its gateway.
-     173                 :            :      * @param _gateway l1 gateway address
-     174                 :            :      * @param _maxGas max gas for L2 retryable exrecution
-     175                 :            :      * @param _gasPriceBid gas price for L2 retryable ticket
-     176                 :            :      * @param  _maxSubmissionCost base submission cost  L2 retryable tick3et
-     177                 :            :      * @param _creditBackAddress address for crediting back overpayment of _maxSubmissionCost
-     178                 :            :      * @return Retryable ticket ID
-     179                 :            :      */
-     180                 :            :     function setGateway(
-     181                 :            :         address _gateway,
-     182                 :            :         uint256 _maxGas,
-     183                 :            :         uint256 _gasPriceBid,
-     184                 :            :         uint256 _maxSubmissionCost,
-     185                 :            :         address _creditBackAddress
-     186                 :            :     ) public payable override returns (uint256) {
-     187         [ +  + ]:          8 :         require(
-     188                 :            :             ArbitrumEnabledToken(msg.sender).isArbitrumEnabled() == uint8(0xb1),
-     189                 :            :             "NOT_ARB_ENABLED"
-     190                 :            :         );
-     191                 :            : 
-     192         [ +  + ]:          7 :         require(Address.isContract(_gateway), "NOT_TO_CONTRACT");
-     193                 :            : 
-     194                 :          6 :         address currGateway = getGateway(msg.sender);
-     195         [ +  # ]:          6 :         if (currGateway != address(0) && currGateway != defaultGateway) {
-     196                 :            :             // if gateway is already set to a non-default gateway, don't allow it to set a different gateway
-     197         [ +  # ]:          1 :             require(currGateway == _gateway, "NO_UPDATE_TO_DIFFERENT_ADDR");
-     198                 :            :         }
-     199                 :            : 
-     200                 :          5 :         address[] memory _tokenArr = new address[](1);
-     201                 :          5 :         _tokenArr[0] = address(msg.sender);
-     202                 :            : 
-     203                 :          5 :         address[] memory _gatewayArr = new address[](1);
-     204                 :          5 :         _gatewayArr[0] = _gateway;
-     205                 :            : 
-     206                 :          5 :         return
-     207                 :            :             _setGateways(
-     208                 :            :                 _tokenArr,
-     209                 :            :                 _gatewayArr,
-     210                 :            :                 _maxGas,
-     211                 :            :                 _gasPriceBid,
-     212                 :            :                 _maxSubmissionCost,
-     213                 :            :                 _creditBackAddress
-     214                 :            :             );
-     215                 :            :     }
-     216                 :            : 
-     217                 :            :     function setGateways(
-     218                 :            :         address[] memory _token,
-     219                 :            :         address[] memory _gateway,
-     220                 :            :         uint256 _maxGas,
-     221                 :            :         uint256 _gasPriceBid,
-     222                 :            :         uint256 _maxSubmissionCost
-     223                 :            :     ) external payable onlyOwner returns (uint256) {
-     224                 :            :         // it is assumed that token and gateway are both contracts
-     225                 :            :         // require(_token[i].isContract() && _gateway[i].isContract(), "NOT_CONTRACT");
-     226                 :          2 :         return
-     227                 :            :             _setGateways(_token, _gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender);
-     228                 :            :     }
-     229                 :            : 
-     230                 :            :     function outboundTransfer(
-     231                 :            :         address _token,
-     232                 :            :         address _to,
-     233                 :            :         uint256 _amount,
-     234                 :            :         uint256 _maxGas,
-     235                 :            :         uint256 _gasPriceBid,
-     236                 :            :         bytes calldata _data
-     237                 :            :     ) public payable override(GatewayRouter, ITokenGateway) returns (bytes memory) {
-     238                 :          0 :         return super.outboundTransfer(_token, _to, _amount, _maxGas, _gasPriceBid, _data);
-     239                 :            :     }
-     240                 :            : 
-     241                 :            :     /**
-     242                 :            :      * @notice Deposit ERC20 token from Ethereum into Arbitrum using the registered or otherwise default gateway
-     243                 :            :      * @dev Some legacy gateway might not have the outboundTransferCustomRefund method and will revert, in such case use outboundTransfer instead
-     244                 :            :      *      L2 address alias will not be applied to the following types of addresses on L1:
-     245                 :            :      *      - an externally-owned account
-     246                 :            :      *      - a contract in construction
-     247                 :            :      *      - an address where a contract will be created
-     248                 :            :      *      - an address where a contract lived, but was destroyed
-     249                 :            :      * @param _token L1 address of ERC20
-     250                 :            :      * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2
-     251                 :            :      * @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
-     252                 :            :                   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
-     253                 :            :      * @param _amount Token Amount
-     254                 :            :      * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution
-     255                 :            :      * @param _gasPriceBid Gas price for L2 execution
-     256                 :            :      * @param _data encoded data from router and user
-     257                 :            :      * @return res abi encoded inbox sequence number
-     258                 :            :      */
-     259                 :            :     function outboundTransferCustomRefund(
-     260                 :            :         address _token,
-     261                 :            :         address _refundTo,
-     262                 :            :         address _to,
-     263                 :            :         uint256 _amount,
-     264                 :            :         uint256 _maxGas,
-     265                 :            :         uint256 _gasPriceBid,
-     266                 :            :         bytes calldata _data
-     267                 :            :     ) public payable override returns (bytes memory) {
-     268                 :          0 :         address gateway = getGateway(_token);
-     269                 :          0 :         bytes memory gatewayData = GatewayMessageHandler.encodeFromRouterToGateway(
-     270                 :            :             msg.sender,
-     271                 :            :             _data
-     272                 :            :         );
-     273                 :            : 
-     274                 :          0 :         emit TransferRouted(_token, msg.sender, _to, gateway);
-     275                 :            :         // here we use `IL1ArbitrumGateway` since we don't assume all ITokenGateway implements `outboundTransferCustomRefund`
-     276                 :          0 :         return
-     277                 :            :             IL1ArbitrumGateway(gateway).outboundTransferCustomRefund{ value: msg.value }(
-     278                 :            :                 _token,
-     279                 :            :                 _refundTo,
-     280                 :            :                 _to,
-     281                 :            :                 _amount,
-     282                 :            :                 _maxGas,
-     283                 :            :                 _gasPriceBid,
-     284                 :            :                 gatewayData
-     285                 :            :             );
-     286                 :            :     }
-     287                 :            : 
-     288                 :            :     modifier onlyCounterpartGateway() override {
-     289                 :            :         // don't expect messages from L2 router
-     290                 :            :         revert("ONLY_COUNTERPART_GATEWAY");
-     291                 :            :         _;
-     292                 :            :     }
-     293                 :            : 
-     294                 :            :     function supportsInterface(bytes4 interfaceId)
-     295                 :            :         public
-     296                 :            :         view
-     297                 :            :         override(ERC165, IERC165)
-     298                 :            :         returns (bool)
-     299                 :            :     {
-     300                 :            :         // registering interfaces that is added after arb-bridge-peripherals >1.0.11
-     301                 :            :         // using function selector instead of single function interfaces to reduce bloat
-     302                 :        256 :         return
-     303                 :            :             interfaceId == this.outboundTransferCustomRefund.selector ||
-     304                 :            :             super.supportsInterface(interfaceId);
-     305                 :            :     }
-     306                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func-sort-c.html deleted file mode 100644 index 95a53a384b..0000000000 --- a/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func-sort-c.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1OrbitERC20Gateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1OrbitERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:33100.0 %
Date:2023-04-27 16:26:32Functions:33100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1OrbitERC20Gateway._createRetryable2
L1OrbitERC20Gateway._initiateDeposit2
L1OrbitERC20Gateway._parseUserEncodedData5
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func.html b/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func.html deleted file mode 100644 index dd31b64e10..0000000000 --- a/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.func.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1OrbitERC20Gateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1OrbitERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:33100.0 %
Date:2023-04-27 16:26:32Functions:33100.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1OrbitERC20Gateway._createRetryable2
L1OrbitERC20Gateway._initiateDeposit2
L1OrbitERC20Gateway._parseUserEncodedData5
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.gcov.html b/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.gcov.html deleted file mode 100644 index e744dc123e..0000000000 --- a/coverage/ethereum/gateway/L1OrbitERC20Gateway.sol.gcov.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1OrbitERC20Gateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1OrbitERC20Gateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:33100.0 %
Date:2023-04-27 16:26:32Functions:33100.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.0;
-       4                 :            : 
-       5                 :            : import "./L1ERC20Gateway.sol";
-       6                 :            : import { IERC20Inbox } from "../L1ArbitrumMessenger.sol";
-       7                 :            : 
-       8                 :            : /**
-       9                 :            :  * @title Layer 1 Gateway contract for bridging standard ERC20s in ERC20-based rollup
-      10                 :            :  * @notice This contract handles token deposits, holds the escrowed tokens on layer 1, and (ultimately) finalizes withdrawals.
-      11                 :            :  * @dev Any ERC20 that requires non-standard functionality should use a separate gateway.
-      12                 :            :  * Messages to layer 2 use the inbox's createRetryableTicket method.
-      13                 :            :  */
-      14                 :            : contract L1OrbitERC20Gateway is L1ERC20Gateway {
-      15                 :            :     function _parseUserEncodedData(
-      16                 :            :         bytes memory data
-      17                 :            :     )
-      18                 :            :         internal
-      19                 :            :         pure
-      20                 :            :         override
-      21                 :            :         returns (uint256 maxSubmissionCost, bytes memory callHookData, uint256 tokenTotalFeeAmount)
-      22                 :            :     {
-      23                 :          5 :         (maxSubmissionCost, callHookData, tokenTotalFeeAmount) = abi.decode(
-      24                 :            :             data,
-      25                 :            :             (uint256, bytes, uint256)
-      26                 :            :         );
-      27                 :            :     }
-      28                 :            : 
-      29                 :            :     function _initiateDeposit(
-      30                 :            :         address _refundTo,
-      31                 :            :         address _from,
-      32                 :            :         uint256,
-      33                 :            :         uint256 _maxGas,
-      34                 :            :         uint256 _gasPriceBid,
-      35                 :            :         uint256 _maxSubmissionCost,
-      36                 :            :         uint256 tokenTotalFeeAmount,
-      37                 :            :         bytes memory _data
-      38                 :            :     ) internal override returns (uint256) {
-      39                 :          2 :         return
-      40                 :            :             sendTxToL2CustomRefund(
-      41                 :            :                 inbox,
-      42                 :            :                 counterpartGateway,
-      43                 :            :                 _refundTo,
-      44                 :            :                 _from,
-      45                 :            :                 tokenTotalFeeAmount,
-      46                 :            :                 0,
-      47                 :            :                 L2GasParams({
-      48                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
-      49                 :            :                     _maxGas: _maxGas,
-      50                 :            :                     _gasPriceBid: _gasPriceBid
-      51                 :            :                 }),
-      52                 :            :                 _data
-      53                 :            :             );
-      54                 :            :     }
-      55                 :            : 
-      56                 :            :     function _createRetryable(
-      57                 :            :         address _inbox,
-      58                 :            :         address _to,
-      59                 :            :         address _refundTo,
-      60                 :            :         address _user,
-      61                 :            :         uint256 _totalFeeAmount,
-      62                 :            :         uint256 _l2CallValue,
-      63                 :            :         uint256 _maxSubmissionCost,
-      64                 :            :         uint256 _maxGas,
-      65                 :            :         uint256 _gasPriceBid,
-      66                 :            :         bytes memory _data
-      67                 :            :     ) internal override returns (uint256) {
-      68                 :          2 :         return
-      69                 :            :             IERC20Inbox(_inbox).createRetryableTicket(
-      70                 :            :                 _to,
-      71                 :            :                 _l2CallValue,
-      72                 :            :                 _maxSubmissionCost,
-      73                 :            :                 _refundTo,
-      74                 :            :                 _user,
-      75                 :            :                 _maxGas,
-      76                 :            :                 _gasPriceBid,
-      77                 :            :                 _totalFeeAmount,
-      78                 :            :                 _data
-      79                 :            :             );
-      80                 :            :     }
-      81                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func-sort-c.html deleted file mode 100644 index d1adb2d646..0000000000 --- a/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ReverseCustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ReverseCustomGateway.inboundEscrowTransfer0
L1ReverseCustomGateway.outboundEscrowTransfer0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func.html b/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func.html deleted file mode 100644 index 8e4312e9af..0000000000 --- a/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ReverseCustomGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1ReverseCustomGateway.inboundEscrowTransfer0
L1ReverseCustomGateway.outboundEscrowTransfer0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.gcov.html b/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.gcov.html deleted file mode 100644 index dd70a984d6..0000000000 --- a/coverage/ethereum/gateway/L1ReverseCustomGateway.sol.gcov.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1ReverseCustomGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1ReverseCustomGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./L1CustomGateway.sol";
-      22                 :            : import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
-      23                 :            : 
-      24                 :            : /**
-      25                 :            :  * @title   L1 Gateway for reverse "custom" bridging functionality
-      26                 :            :  * @notice  Handles some (but not all!) reverse custom Gateway needs.
-      27                 :            :  *          Use the reverse custom gateway instead of the normal custom
-      28                 :            :  *          gateway if you want total supply to be tracked on the L2
-      29                 :            :  *          rather than the L1.
-      30                 :            :  * @dev     The reverse custom gateway burns on the l2 and escrows on the l1
-      31                 :            :  *          which is the opposite of the way the normal custom gateway works
-      32                 :            :  *          This means that the total supply L2 isn't affected by briding, which
-      33                 :            :  *          is helpful for observers calculating the total supply especially if
-      34                 :            :  *          if minting is also occuring on L2
-      35                 :            :  */
-      36                 :            : contract L1ReverseCustomGateway is L1CustomGateway {
-      37                 :            :     function inboundEscrowTransfer(
-      38                 :            :         address _l1Address,
-      39                 :            :         address _dest,
-      40                 :            :         uint256 _amount
-      41                 :            :     ) internal virtual override {
-      42                 :          0 :         IArbToken(_l1Address).bridgeMint(_dest, _amount);
-      43                 :            :     }
-      44                 :            : 
-      45                 :            :     function outboundEscrowTransfer(
-      46                 :            :         address _l1Token,
-      47                 :            :         address _from,
-      48                 :            :         uint256 _amount
-      49                 :            :     ) internal override returns (uint256) {
-      50                 :          0 :         IArbToken(_l1Token).bridgeBurn(_from, _amount);
-      51                 :            :         // by default we assume that the amount we send to bridgeBurn is the amount burnt
-      52                 :            :         // this might not be the case for every token
-      53                 :          0 :         return _amount;
-      54                 :            :     }
-      55                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1WethGateway.sol.func-sort-c.html b/coverage/ethereum/gateway/L1WethGateway.sol.func-sort-c.html deleted file mode 100644 index e9b62d29ac..0000000000 --- a/coverage/ethereum/gateway/L1WethGateway.sol.func-sort-c.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1WethGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0150.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1WethGateway.calculateL2TokenAddress0
L1WethGateway.createOutboundTxCustomRefund0
L1WethGateway.inboundEscrowTransfer0
L1WethGateway.initialize0
L1WethGateway.outboundEscrowTransfer0
L1WethGateway.setRedirectedExit0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1WethGateway.sol.func.html b/coverage/ethereum/gateway/L1WethGateway.sol.func.html deleted file mode 100644 index f1a1333fd0..0000000000 --- a/coverage/ethereum/gateway/L1WethGateway.sol.func.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1WethGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0150.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L1WethGateway.calculateL2TokenAddress0
L1WethGateway.createOutboundTxCustomRefund0
L1WethGateway.inboundEscrowTransfer0
L1WethGateway.initialize0
L1WethGateway.outboundEscrowTransfer0
L1WethGateway.setRedirectedExit0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/L1WethGateway.sol.gcov.html b/coverage/ethereum/gateway/L1WethGateway.sol.gcov.html deleted file mode 100644 index 7379cf26ff..0000000000 --- a/coverage/ethereum/gateway/L1WethGateway.sol.gcov.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway/L1WethGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gateway - L1WethGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0150.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:060.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "@arbitrum/nitro-contracts/src/bridge/IInbox.sol";
-      22                 :            : import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
-      23                 :            : import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
-      24                 :            : import "../../libraries/IWETH9.sol";
-      25                 :            : import "../../test/TestWETH9.sol";
-      26                 :            : import "./L1ArbitrumExtendedGateway.sol";
-      27                 :            : 
-      28                 :            : contract L1WethGateway is L1ArbitrumExtendedGateway {
-      29                 :            :     using SafeERC20 for IERC20;
-      30                 :            : 
-      31                 :            :     address public l1Weth;
-      32                 :            :     address public l2Weth;
-      33                 :            : 
-      34                 :            :     function initialize(
-      35                 :            :         address _l2Counterpart,
-      36                 :            :         address _l1Router,
-      37                 :            :         address _inbox,
-      38                 :            :         address _l1Weth,
-      39                 :            :         address _l2Weth
-      40                 :            :     ) public {
-      41                 :          0 :         L1ArbitrumGateway._initialize(_l2Counterpart, _l1Router, _inbox);
-      42         [ #  # ]:          0 :         require(_l1Weth != address(0), "INVALID_L1WETH");
-      43         [ #  # ]:          0 :         require(_l2Weth != address(0), "INVALID_L2WETH");
-      44                 :          0 :         l1Weth = _l1Weth;
-      45                 :          0 :         l2Weth = _l2Weth;
-      46                 :            :     }
-      47                 :            : 
-      48                 :            :     function createOutboundTxCustomRefund(
-      49                 :            :         address _refundTo,
-      50                 :            :         address _from,
-      51                 :            :         uint256 _tokenAmount,
-      52                 :            :         uint256 _maxGas,
-      53                 :            :         uint256 _gasPriceBid,
-      54                 :            :         uint256 _maxSubmissionCost,
-      55                 :            :         bytes memory _outboundCalldata
-      56                 :            :     ) internal override returns (uint256) {
-      57                 :          0 :         return
-      58                 :            :             sendTxToL2CustomRefund(
-      59                 :            :                 inbox,
-      60                 :            :                 counterpartGateway,
-      61                 :            :                 _refundTo,
-      62                 :            :                 _from,
-      63                 :            :                 // msg.value does not include weth withdrawn from user, we need to add in that amount
-      64                 :            :                 msg.value + _tokenAmount,
-      65                 :            :                 // send token amount to L2 as call value
-      66                 :            :                 _tokenAmount,
-      67                 :            :                 L2GasParams({
-      68                 :            :                     _maxSubmissionCost: _maxSubmissionCost,
-      69                 :            :                     _maxGas: _maxGas,
-      70                 :            :                     _gasPriceBid: _gasPriceBid
-      71                 :            :                 }),
-      72                 :            :                 _outboundCalldata
-      73                 :            :             );
-      74                 :            :     }
-      75                 :            : 
-      76                 :            :     function outboundEscrowTransfer(
-      77                 :            :         address _l1Token,
-      78                 :            :         address _from,
-      79                 :            :         uint256 _amount
-      80                 :            :     ) internal override returns (uint256) {
-      81                 :          0 :         IERC20(_l1Token).safeTransferFrom(_from, address(this), _amount);
-      82                 :          0 :         IWETH9(_l1Token).withdraw(_amount);
-      83                 :            :         // the weth token doesn't contain any special behaviour that changes the amount
-      84                 :            :         // when doing transfers / withdrawals. so we don't check the balanceOf
-      85                 :          0 :         return _amount;
-      86                 :            :     }
-      87                 :            : 
-      88                 :            :     function inboundEscrowTransfer(
-      89                 :            :         address _l1Token,
-      90                 :            :         address _dest,
-      91                 :            :         uint256 _amount
-      92                 :            :     ) internal override {
-      93                 :          0 :         IWETH9(_l1Token).deposit{ value: _amount }();
-      94                 :          0 :         IERC20(_l1Token).safeTransfer(_dest, _amount);
-      95                 :            :     }
-      96                 :            : 
-      97                 :            :     /**
-      98                 :            :      * @notice Calculate the address used when bridging an ERC20 token
-      99                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
-     100                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
-     101                 :            :      * @param l1ERC20 address of L1 token
-     102                 :            :      * @return L2 address of a bridged ERC20 token
-     103                 :            :      */
-     104                 :            :     function calculateL2TokenAddress(address l1ERC20) public view override(ITokenGateway, TokenGateway) returns (address) {
-     105         [ #  # ]:          0 :         if (l1ERC20 != l1Weth) {
-     106                 :            :             // invalid L1 weth address
-     107                 :          0 :             return address(0);
-     108                 :            :         }
-     109                 :          0 :         return l2Weth;
-     110                 :            :     }
-     111                 :            : 
-     112                 :            :     /**
-     113                 :            :      * @notice  Temporary disable the ability to trade exits
-     114                 :            :      */
-     115                 :            :     function setRedirectedExit(
-     116                 :            :         uint256 _exitNum,
-     117                 :            :         address _initialDestination,
-     118                 :            :         address _newDestination,
-     119                 :            :         bytes memory _newData
-     120                 :            :     ) internal override {
-     121                 :          0 :         revert("TRADABLE_EXIT_TEMP_DISABLED");
-     122                 :            :     }
-     123                 :            : 
-     124                 :            :     receive() external payable {}
-     125                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/index-sort-b.html b/coverage/ethereum/gateway/index-sort-b.html deleted file mode 100644 index 70dd8915ea..0000000000 --- a/coverage/ethereum/gateway/index-sort-b.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gatewayHitTotalCoverage
Test:lcov.infoLines:12817374.0 %
Date:2023-04-27 16:26:32Functions:355366.0 %
Branches:406858.8 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1WethGateway.sol -
0.0%
-
0.0 %0 / 150.0 %0 / 60.0 %0 / 6
L1CustomGateway.sol -
57.1%57.1%
-
57.1 %16 / 2842.9 %3 / 710.0 %1 / 10
L1ArbitrumGateway.sol -
81.2%81.2%
-
81.2 %39 / 4878.6 %11 / 1466.7 %12 / 18
L1GatewayRouter.sol -
87.5%87.5%
-
87.5 %35 / 4077.8 %7 / 972.2 %13 / 18
L1ArbitrumExtendedGateway.sol -
100.0%
-
100.0 %17 / 17100.0 %4 / 483.3 %10 / 12
L1OrbitERC20Gateway.sol -
100.0%
-
100.0 %3 / 3100.0 %3 / 3-0 / 0
L1ForceOnlyReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
L1ReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 2-0 / 0
L1ERC20Gateway.sol -
100.0%
-
100.0 %18 / 18100.0 %7 / 7100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/index-sort-f.html b/coverage/ethereum/gateway/index-sort-f.html deleted file mode 100644 index 90cce7812f..0000000000 --- a/coverage/ethereum/gateway/index-sort-f.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gatewayHitTotalCoverage
Test:lcov.infoLines:12817374.0 %
Date:2023-04-27 16:26:32Functions:355366.0 %
Branches:406858.8 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ForceOnlyReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
L1ReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 2-0 / 0
L1WethGateway.sol -
0.0%
-
0.0 %0 / 150.0 %0 / 60.0 %0 / 6
L1CustomGateway.sol -
57.1%57.1%
-
57.1 %16 / 2842.9 %3 / 710.0 %1 / 10
L1GatewayRouter.sol -
87.5%87.5%
-
87.5 %35 / 4077.8 %7 / 972.2 %13 / 18
L1ArbitrumGateway.sol -
81.2%81.2%
-
81.2 %39 / 4878.6 %11 / 1466.7 %12 / 18
L1OrbitERC20Gateway.sol -
100.0%
-
100.0 %3 / 3100.0 %3 / 3-0 / 0
L1ArbitrumExtendedGateway.sol -
100.0%
-
100.0 %17 / 17100.0 %4 / 483.3 %10 / 12
L1ERC20Gateway.sol -
100.0%
-
100.0 %18 / 18100.0 %7 / 7100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/index-sort-l.html b/coverage/ethereum/gateway/index-sort-l.html deleted file mode 100644 index da8eca2e37..0000000000 --- a/coverage/ethereum/gateway/index-sort-l.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gatewayHitTotalCoverage
Test:lcov.infoLines:12817374.0 %
Date:2023-04-27 16:26:32Functions:355366.0 %
Branches:406858.8 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ForceOnlyReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
L1ReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 2-0 / 0
L1WethGateway.sol -
0.0%
-
0.0 %0 / 150.0 %0 / 60.0 %0 / 6
L1CustomGateway.sol -
57.1%57.1%
-
57.1 %16 / 2842.9 %3 / 710.0 %1 / 10
L1ArbitrumGateway.sol -
81.2%81.2%
-
81.2 %39 / 4878.6 %11 / 1466.7 %12 / 18
L1GatewayRouter.sol -
87.5%87.5%
-
87.5 %35 / 4077.8 %7 / 972.2 %13 / 18
L1OrbitERC20Gateway.sol -
100.0%
-
100.0 %3 / 3100.0 %3 / 3-0 / 0
L1ArbitrumExtendedGateway.sol -
100.0%
-
100.0 %17 / 17100.0 %4 / 483.3 %10 / 12
L1ERC20Gateway.sol -
100.0%
-
100.0 %18 / 18100.0 %7 / 7100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/gateway/index.html b/coverage/ethereum/gateway/index.html deleted file mode 100644 index 35ad39b6a7..0000000000 --- a/coverage/ethereum/gateway/index.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereum/gatewayHitTotalCoverage
Test:lcov.infoLines:12817374.0 %
Date:2023-04-27 16:26:32Functions:355366.0 %
Branches:406858.8 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumExtendedGateway.sol -
100.0%
-
100.0 %17 / 17100.0 %4 / 483.3 %10 / 12
L1ArbitrumGateway.sol -
81.2%81.2%
-
81.2 %39 / 4878.6 %11 / 1466.7 %12 / 18
L1CustomGateway.sol -
57.1%57.1%
-
57.1 %16 / 2842.9 %3 / 710.0 %1 / 10
L1ERC20Gateway.sol -
100.0%
-
100.0 %18 / 18100.0 %7 / 7100.0 %4 / 4
L1ForceOnlyReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
L1GatewayRouter.sol -
87.5%87.5%
-
87.5 %35 / 4077.8 %7 / 972.2 %13 / 18
L1OrbitERC20Gateway.sol -
100.0%
-
100.0 %3 / 3100.0 %3 / 3-0 / 0
L1ReverseCustomGateway.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 2-0 / 0
L1WethGateway.sol -
0.0%
-
0.0 %0 / 150.0 %0 / 60.0 %0 / 6
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/index-sort-b.html b/coverage/ethereum/index-sort-b.html deleted file mode 100644 index 69c3172fee..0000000000 --- a/coverage/ethereum/index-sort-b.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereumHitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumMessenger.sol -
100.0%
-
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/index-sort-f.html b/coverage/ethereum/index-sort-f.html deleted file mode 100644 index 1c00fa4037..0000000000 --- a/coverage/ethereum/index-sort-f.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereumHitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumMessenger.sol -
100.0%
-
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/index-sort-l.html b/coverage/ethereum/index-sort-l.html deleted file mode 100644 index 3947fd0349..0000000000 --- a/coverage/ethereum/index-sort-l.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereumHitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumMessenger.sol -
100.0%
-
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ethereum/index.html b/coverage/ethereum/index.html deleted file mode 100644 index 78fa0bfb1e..0000000000 --- a/coverage/ethereum/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - LCOV - lcov.info - ethereum - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - ethereumHitTotalCoverage
Test:lcov.infoLines:1212100.0 %
Date:2023-04-27 16:26:32Functions:55100.0 %
Branches:1250.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L1ArbitrumMessenger.sol -
100.0%
-
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/gcov.css b/coverage/gcov.css deleted file mode 100644 index 0fcdff13ce..0000000000 --- a/coverage/gcov.css +++ /dev/null @@ -1,519 +0,0 @@ -/* All views: initial background and text color */ -body -{ - color: #000000; - background-color: #ffffff; -} - -/* All views: standard link format*/ -a:link -{ - color: #284fa8; - text-decoration: underline; -} - -/* All views: standard link - visited format */ -a:visited -{ - color: #00cb40; - text-decoration: underline; -} - -/* All views: standard link - activated format */ -a:active -{ - color: #ff0040; - text-decoration: underline; -} - -/* All views: main title format */ -td.title -{ - text-align: center; - padding-bottom: 10px; - font-family: sans-serif; - font-size: 20pt; - font-style: italic; - font-weight: bold; -} - -/* All views: header item format */ -td.headerItem -{ - text-align: right; - padding-right: 6px; - font-family: sans-serif; - font-weight: bold; - vertical-align: top; - white-space: nowrap; -} - -/* All views: header item value format */ -td.headerValue -{ - text-align: left; - color: #284fa8; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; -} - -/* All views: header item coverage table heading */ -td.headerCovTableHead -{ - text-align: center; - padding-right: 6px; - padding-left: 6px; - padding-bottom: 0px; - font-family: sans-serif; - font-size: 80%; - white-space: nowrap; -} - -/* All views: header item coverage table entry */ -td.headerCovTableEntry -{ - text-align: right; - color: #284fa8; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #dae7fe; -} - -/* All views: header item coverage table entry for high coverage rate */ -td.headerCovTableEntryHi -{ - text-align: right; - color: #000000; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #a7fc9d; -} - -/* All views: header item coverage table entry for medium coverage rate */ -td.headerCovTableEntryMed -{ - text-align: right; - color: #000000; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #ffea20; -} - -/* All views: header item coverage table entry for ow coverage rate */ -td.headerCovTableEntryLo -{ - text-align: right; - color: #000000; - font-family: sans-serif; - font-weight: bold; - white-space: nowrap; - padding-left: 12px; - padding-right: 4px; - background-color: #ff0000; -} - -/* All views: header legend value for legend entry */ -td.headerValueLeg -{ - text-align: left; - color: #000000; - font-family: sans-serif; - font-size: 80%; - white-space: nowrap; - padding-top: 4px; -} - -/* All views: color of horizontal ruler */ -td.ruler -{ - background-color: #6688d4; -} - -/* All views: version string format */ -td.versionInfo -{ - text-align: center; - padding-top: 2px; - font-family: sans-serif; - font-style: italic; -} - -/* Directory view/File view (all)/Test case descriptions: - table headline format */ -td.tableHead -{ - text-align: center; - color: #ffffff; - background-color: #6688d4; - font-family: sans-serif; - font-size: 120%; - font-weight: bold; - white-space: nowrap; - padding-left: 4px; - padding-right: 4px; -} - -span.tableHeadSort -{ - padding-right: 4px; -} - -/* Directory view/File view (all): filename entry format */ -td.coverFile -{ - text-align: left; - padding-left: 10px; - padding-right: 20px; - color: #284fa8; - background-color: #dae7fe; - font-family: monospace; -} - -/* Directory view/File view (all): bar-graph entry format*/ -td.coverBar -{ - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; -} - -/* Directory view/File view (all): bar-graph outline color */ -td.coverBarOutline -{ - background-color: #000000; -} - -/* Directory view/File view (all): percentage entry for files with - high coverage rate */ -td.coverPerHi -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #a7fc9d; - font-weight: bold; - font-family: sans-serif; -} - -/* Directory view/File view (all): line count entry for files with - high coverage rate */ -td.coverNumHi -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #a7fc9d; - white-space: nowrap; - font-family: sans-serif; -} - -/* Directory view/File view (all): percentage entry for files with - medium coverage rate */ -td.coverPerMed -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ffea20; - font-weight: bold; - font-family: sans-serif; -} - -/* Directory view/File view (all): line count entry for files with - medium coverage rate */ -td.coverNumMed -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ffea20; - white-space: nowrap; - font-family: sans-serif; -} - -/* Directory view/File view (all): percentage entry for files with - low coverage rate */ -td.coverPerLo -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ff0000; - font-weight: bold; - font-family: sans-serif; -} - -/* Directory view/File view (all): line count entry for files with - low coverage rate */ -td.coverNumLo -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ff0000; - white-space: nowrap; - font-family: sans-serif; -} - -/* File view (all): "show/hide details" link format */ -a.detail:link -{ - color: #B8D0FF; - font-size:80%; -} - -/* File view (all): "show/hide details" link - visited format */ -a.detail:visited -{ - color: #B8D0FF; - font-size:80%; -} - -/* File view (all): "show/hide details" link - activated format */ -a.detail:active -{ - color: #ffffff; - font-size:80%; -} - -/* File view (detail): test name entry */ -td.testName -{ - text-align: right; - padding-right: 10px; - background-color: #dae7fe; - font-family: sans-serif; -} - -/* File view (detail): test percentage entry */ -td.testPer -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; - font-family: sans-serif; -} - -/* File view (detail): test lines count entry */ -td.testNum -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; - font-family: sans-serif; -} - -/* Test case descriptions: test name format*/ -dt -{ - font-family: sans-serif; - font-weight: bold; -} - -/* Test case descriptions: description table body */ -td.testDescription -{ - padding-top: 10px; - padding-left: 30px; - padding-bottom: 10px; - padding-right: 30px; - background-color: #dae7fe; -} - -/* Source code view: function entry */ -td.coverFn -{ - text-align: left; - padding-left: 10px; - padding-right: 20px; - color: #284fa8; - background-color: #dae7fe; - font-family: monospace; -} - -/* Source code view: function entry zero count*/ -td.coverFnLo -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #ff0000; - font-weight: bold; - font-family: sans-serif; -} - -/* Source code view: function entry nonzero count*/ -td.coverFnHi -{ - text-align: right; - padding-left: 10px; - padding-right: 10px; - background-color: #dae7fe; - font-weight: bold; - font-family: sans-serif; -} - -/* Source code view: source code format */ -pre.source -{ - font-family: monospace; - white-space: pre; - margin-top: 2px; -} - -/* Source code view: line number format */ -span.lineNum -{ - background-color: #efe383; -} - -/* Source code view: format for lines which were executed */ -td.lineCov, -span.lineCov -{ - background-color: #cad7fe; -} - -/* Source code view: format for Cov legend */ -span.coverLegendCov -{ - padding-left: 10px; - padding-right: 10px; - padding-bottom: 2px; - background-color: #cad7fe; -} - -/* Source code view: format for lines which were not executed */ -td.lineNoCov, -span.lineNoCov -{ - background-color: #ff6230; -} - -/* Source code view: format for NoCov legend */ -span.coverLegendNoCov -{ - padding-left: 10px; - padding-right: 10px; - padding-bottom: 2px; - background-color: #ff6230; -} - -/* Source code view (function table): standard link - visited format */ -td.lineNoCov > a:visited, -td.lineCov > a:visited -{ - color: #000000; - text-decoration: underline; -} - -/* Source code view: format for lines which were executed only in a - previous version */ -span.lineDiffCov -{ - background-color: #b5f7af; -} - -/* Source code view: format for branches which were executed - * and taken */ -span.branchCov -{ - background-color: #cad7fe; -} - -/* Source code view: format for branches which were executed - * but not taken */ -span.branchNoCov -{ - background-color: #ff6230; -} - -/* Source code view: format for branches which were not executed */ -span.branchNoExec -{ - background-color: #ff6230; -} - -/* Source code view: format for the source code heading line */ -pre.sourceHeading -{ - white-space: pre; - font-family: monospace; - font-weight: bold; - margin: 0px; -} - -/* All views: header legend value for low rate */ -td.headerValueLegL -{ - font-family: sans-serif; - text-align: center; - white-space: nowrap; - padding-left: 4px; - padding-right: 2px; - background-color: #ff0000; - font-size: 80%; -} - -/* All views: header legend value for med rate */ -td.headerValueLegM -{ - font-family: sans-serif; - text-align: center; - white-space: nowrap; - padding-left: 2px; - padding-right: 2px; - background-color: #ffea20; - font-size: 80%; -} - -/* All views: header legend value for hi rate */ -td.headerValueLegH -{ - font-family: sans-serif; - text-align: center; - white-space: nowrap; - padding-left: 2px; - padding-right: 4px; - background-color: #a7fc9d; - font-size: 80%; -} - -/* All views except source code view: legend format for low coverage */ -span.coverLegendCovLo -{ - padding-left: 10px; - padding-right: 10px; - padding-top: 2px; - background-color: #ff0000; -} - -/* All views except source code view: legend format for med coverage */ -span.coverLegendCovMed -{ - padding-left: 10px; - padding-right: 10px; - padding-top: 2px; - background-color: #ffea20; -} - -/* All views except source code view: legend format for hi coverage */ -span.coverLegendCovHi -{ - padding-left: 10px; - padding-right: 10px; - padding-top: 2px; - background-color: #a7fc9d; -} diff --git a/coverage/glass.png b/coverage/glass.png deleted file mode 100644 index e1abc00680a3093c49fdb775ae6bdb6764c95af2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)gaEa{HEjtmSN`?>!lvI6;R0X`wF z|Ns97GD8ntt^-nxB|(0{3=Yq3q=7g|-tI089jvk*Kn`btM`SSr1Gf+eGhVt|_XjA* zUgGKN%6^Gmn4d%Ph(nkFP>9RZ#WAE}PI3Z}&BVayv3^M*kj3EX>gTe~DWM4f=_Dpv diff --git a/coverage/index-sort-b.html b/coverage/index-sort-b.html deleted file mode 100644 index c244bb0320..0000000000 --- a/coverage/index-sort-b.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - LCOV - lcov.info - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:21163533.2 %
Date:2023-04-27 16:26:32Functions:6623628.0 %
Branches:6322627.9 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
arbitrum -
0.0%
-
0.0 %0 / 170.0 %0 / 70.0 %0 / 6
/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils -
0.0%
-
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
arbitrum/gateway -
0.0%
-
0.0 %0 / 980.0 %0 / 290.0 %0 / 38
test -
22.4%22.4%
-
22.4 %15 / 6718.9 %7 / 3714.3 %2 / 14
libraries -
22.9%22.9%
-
22.9 %39 / 17022.6 %14 / 6215.6 %10 / 64
ethereum -
100.0%
-
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
ethereum/gateway -
74.0%74.0%
-
74.0 %128 / 17366.0 %35 / 5358.8 %40 / 68
libraries/gateway -
45.5%45.5%
-
45.5 %15 / 3326.7 %4 / 1571.4 %10 / 14
/Users/goran/repos/offchain/token-bridge-contracts/test-foundry -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/index-sort-f.html b/coverage/index-sort-f.html deleted file mode 100644 index 11471f8a22..0000000000 --- a/coverage/index-sort-f.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - LCOV - lcov.info - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:21163533.2 %
Date:2023-04-27 16:26:32Functions:6623628.0 %
Branches:6322627.9 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
arbitrum -
0.0%
-
0.0 %0 / 170.0 %0 / 70.0 %0 / 6
/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils -
0.0%
-
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
arbitrum/gateway -
0.0%
-
0.0 %0 / 980.0 %0 / 290.0 %0 / 38
test -
22.4%22.4%
-
22.4 %15 / 6718.9 %7 / 3714.3 %2 / 14
libraries -
22.9%22.9%
-
22.9 %39 / 17022.6 %14 / 6215.6 %10 / 64
libraries/gateway -
45.5%45.5%
-
45.5 %15 / 3326.7 %4 / 1571.4 %10 / 14
ethereum/gateway -
74.0%74.0%
-
74.0 %128 / 17366.0 %35 / 5358.8 %40 / 68
/Users/goran/repos/offchain/token-bridge-contracts/test-foundry -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
ethereum -
100.0%
-
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/index-sort-l.html b/coverage/index-sort-l.html deleted file mode 100644 index 192d3c52be..0000000000 --- a/coverage/index-sort-l.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - LCOV - lcov.info - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:21163533.2 %
Date:2023-04-27 16:26:32Functions:6623628.0 %
Branches:6322627.9 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
arbitrum -
0.0%
-
0.0 %0 / 170.0 %0 / 70.0 %0 / 6
/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils -
0.0%
-
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
arbitrum/gateway -
0.0%
-
0.0 %0 / 980.0 %0 / 290.0 %0 / 38
test -
22.4%22.4%
-
22.4 %15 / 6718.9 %7 / 3714.3 %2 / 14
libraries -
22.9%22.9%
-
22.9 %39 / 17022.6 %14 / 6215.6 %10 / 64
libraries/gateway -
45.5%45.5%
-
45.5 %15 / 3326.7 %4 / 1571.4 %10 / 14
ethereum/gateway -
74.0%74.0%
-
74.0 %128 / 17366.0 %35 / 5358.8 %40 / 68
/Users/goran/repos/offchain/token-bridge-contracts/test-foundry -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
ethereum -
100.0%
-
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/index.html b/coverage/index.html deleted file mode 100644 index 646fd861a2..0000000000 --- a/coverage/index.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - LCOV - lcov.info - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top levelHitTotalCoverage
Test:lcov.infoLines:21163533.2 %
Date:2023-04-27 16:26:32Functions:6623628.0 %
Branches:6322627.9 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Directory Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
/Users/goran/repos/offchain/token-bridge-contracts/contracts/rpc-utils -
0.0%
-
0.0 %0 / 630.0 %0 / 270.0 %0 / 20
/Users/goran/repos/offchain/token-bridge-contracts/test-foundry -
100.0%
-
100.0 %2 / 2100.0 %1 / 1-0 / 0
arbitrum -
0.0%
-
0.0 %0 / 170.0 %0 / 70.0 %0 / 6
arbitrum/gateway -
0.0%
-
0.0 %0 / 980.0 %0 / 290.0 %0 / 38
ethereum -
100.0%
-
100.0 %12 / 12100.0 %5 / 550.0 %1 / 2
ethereum/gateway -
74.0%74.0%
-
74.0 %128 / 17366.0 %35 / 5358.8 %40 / 68
libraries -
22.9%22.9%
-
22.9 %39 / 17022.6 %14 / 6215.6 %10 / 64
libraries/gateway -
45.5%45.5%
-
45.5 %15 / 3326.7 %4 / 1571.4 %10 / 14
test -
22.4%22.4%
-
22.4 %15 / 6718.9 %7 / 3714.3 %2 / 14
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/AddressAliasHelper.sol.func-sort-c.html b/coverage/libraries/AddressAliasHelper.sol.func-sort-c.html deleted file mode 100644 index 342e092c2d..0000000000 --- a/coverage/libraries/AddressAliasHelper.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/AddressAliasHelper.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - AddressAliasHelper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
AddressAliasHelper.applyL1ToL2Alias0
AddressAliasHelper.undoL1ToL2Alias0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/AddressAliasHelper.sol.func.html b/coverage/libraries/AddressAliasHelper.sol.func.html deleted file mode 100644 index b0faa2edd1..0000000000 --- a/coverage/libraries/AddressAliasHelper.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/AddressAliasHelper.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - AddressAliasHelper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
AddressAliasHelper.applyL1ToL2Alias0
AddressAliasHelper.undoL1ToL2Alias0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/AddressAliasHelper.sol.gcov.html b/coverage/libraries/AddressAliasHelper.sol.gcov.html deleted file mode 100644 index 5b87a4c4c3..0000000000 --- a/coverage/libraries/AddressAliasHelper.sol.gcov.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/AddressAliasHelper.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - AddressAliasHelper.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2019-2021, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : library AddressAliasHelper {
-      22                 :            :     uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);
-      23                 :            : 
-      24                 :            :     /// @notice Utility function that converts the address in the L1 that submitted a tx to
-      25                 :            :     /// the inbox to the msg.sender viewed in the L2
-      26                 :            :     /// @param l1Address the address in the L1 that triggered the tx to L2
-      27                 :            :     /// @return l2Address L2 address as viewed in msg.sender
-      28                 :            :     function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {
-      29                 :            :         unchecked {
-      30                 :          0 :             l2Address = address(uint160(l1Address) + offset);
-      31                 :            :         }
-      32                 :            :     }
-      33                 :            : 
-      34                 :            :     /// @notice Utility function that converts the msg.sender viewed in the L2 to the
-      35                 :            :     /// address in the L1 that submitted a tx to the inbox
-      36                 :            :     /// @param l2Address L2 address as viewed in msg.sender
-      37                 :            :     /// @return l1Address the address in the L1 that triggered the tx to L2
-      38                 :            :     function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {
-      39                 :            :         unchecked {
-      40                 :          0 :             l1Address = address(uint160(l2Address) - offset);
-      41                 :            :         }
-      42                 :            :     }
-      43                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/BytesLib.sol.func-sort-c.html b/coverage/libraries/BytesLib.sol.func-sort-c.html deleted file mode 100644 index f8de1a1f9e..0000000000 --- a/coverage/libraries/BytesLib.sol.func-sort-c.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/BytesLib.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - BytesLib.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:080.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
BytesLib.toAddress0
BytesLib.toBytes320
BytesLib.toUint0
BytesLib.toUint80
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/BytesLib.sol.func.html b/coverage/libraries/BytesLib.sol.func.html deleted file mode 100644 index 6ece999e67..0000000000 --- a/coverage/libraries/BytesLib.sol.func.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/BytesLib.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - BytesLib.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:080.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
BytesLib.toAddress0
BytesLib.toBytes320
BytesLib.toUint0
BytesLib.toUint80
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/BytesLib.sol.gcov.html b/coverage/libraries/BytesLib.sol.gcov.html deleted file mode 100644 index 8d4237f627..0000000000 --- a/coverage/libraries/BytesLib.sol.gcov.html +++ /dev/null @@ -1,144 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/BytesLib.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - BytesLib.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:080.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MIT
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * @title Solidity Bytes Arrays Utils
-       5                 :            :  * @author Gonçalo Sá <goncalo.sa@consensys.net>
-       6                 :            :  *
-       7                 :            :  * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
-       8                 :            :  *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
-       9                 :            :  */
-      10                 :            : 
-      11                 :            : pragma solidity ^0.8.0;
-      12                 :            : 
-      13                 :            : /* solhint-disable no-inline-assembly */
-      14                 :            : library BytesLib {
-      15                 :            :     function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
-      16         [ #  # ]:          0 :         require(_bytes.length >= (_start + 20), "Read out of bounds");
-      17                 :          0 :         address tempAddress;
-      18                 :            : 
-      19                 :            :         assembly {
-      20                 :          0 :             tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
-      21                 :            :         }
-      22                 :            : 
-      23                 :          0 :         return tempAddress;
-      24                 :            :     }
-      25                 :            : 
-      26                 :            :     function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
-      27         [ #  # ]:          0 :         require(_bytes.length >= (_start + 1), "Read out of bounds");
-      28                 :          0 :         uint8 tempUint;
-      29                 :            : 
-      30                 :            :         assembly {
-      31                 :          0 :             tempUint := mload(add(add(_bytes, 0x1), _start))
-      32                 :            :         }
-      33                 :            : 
-      34                 :          0 :         return tempUint;
-      35                 :            :     }
-      36                 :            : 
-      37                 :            :     function toUint(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
-      38         [ #  # ]:          0 :         require(_bytes.length >= (_start + 32), "Read out of bounds");
-      39                 :          0 :         uint256 tempUint;
-      40                 :            : 
-      41                 :            :         assembly {
-      42                 :          0 :             tempUint := mload(add(add(_bytes, 0x20), _start))
-      43                 :            :         }
-      44                 :            : 
-      45                 :          0 :         return tempUint;
-      46                 :            :     }
-      47                 :            : 
-      48                 :            :     function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
-      49         [ #  # ]:          0 :         require(_bytes.length >= (_start + 32), "Read out of bounds");
-      50                 :          0 :         bytes32 tempBytes32;
-      51                 :            : 
-      52                 :            :         assembly {
-      53                 :          0 :             tempBytes32 := mload(add(add(_bytes, 0x20), _start))
-      54                 :            :         }
-      55                 :            : 
-      56                 :          0 :         return tempBytes32;
-      57                 :            :     }
-      58                 :            : }
-      59                 :            : /* solhint-enable no-inline-assembly */
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/BytesParser.sol.func-sort-c.html b/coverage/libraries/BytesParser.sol.func-sort-c.html deleted file mode 100644 index e308feaec2..0000000000 --- a/coverage/libraries/BytesParser.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/BytesParser.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - BytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0210.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:0100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
BytesParser.toString0
BytesParser.toUint80
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/BytesParser.sol.func.html b/coverage/libraries/BytesParser.sol.func.html deleted file mode 100644 index ab09f3d5d9..0000000000 --- a/coverage/libraries/BytesParser.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/BytesParser.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - BytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0210.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:0100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
BytesParser.toString0
BytesParser.toUint80
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/BytesParser.sol.gcov.html b/coverage/libraries/BytesParser.sol.gcov.html deleted file mode 100644 index c87cd97682..0000000000 --- a/coverage/libraries/BytesParser.sol.gcov.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/BytesParser.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - BytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0210.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:0100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./BytesLib.sol";
-      22                 :            : 
-      23                 :            : library BytesParser {
-      24                 :            :     using BytesLib for bytes;
-      25                 :            : 
-      26                 :            :     function toUint8(bytes memory input) internal pure returns (bool success, uint8 res) {
-      27         [ #  # ]:          0 :         if (input.length != 32) {
-      28                 :          0 :             return (false, 0);
-      29                 :            :         }
-      30                 :            :         // TODO: try catch to handle error
-      31                 :          0 :         uint256 inputNum = abi.decode(input, (uint256));
-      32         [ #  # ]:          0 :         if (inputNum > type(uint8).max) {
-      33                 :          0 :             return (false, 0);
-      34                 :            :         }
-      35                 :          0 :         res = uint8(inputNum);
-      36                 :          0 :         success = true;
-      37                 :            :     }
-      38                 :            : 
-      39                 :            :     function toString(bytes memory input) internal pure returns (bool success, string memory res) {
-      40         [ #  # ]:          0 :         if (input.length == 0) {
-      41                 :          0 :             success = false;
-      42                 :            :             // return default value of string
-      43         [ #  # ]:          0 :         } else if (input.length == 32) {
-      44                 :            :             // TODO: can validate anything other than length and being null terminated?
-      45         [ #  # ]:          0 :             if (input[31] != bytes1(0x00)) return (false, res);
-      46                 :          0 :             else success = true;
-      47                 :            : 
-      48                 :            :             // here we assume its a null terminated Bytes32 string
-      49                 :            :             // https://github.com/ethereum/solidity/blob/5852972ec148bc041909400affc778dee66d384d/test/libsolidity/semanticTests/externalContracts/_stringutils/stringutils.sol#L89
-      50                 :            :             // https://github.com/Arachnid/solidity-stringutils
-      51                 :          0 :             uint256 len = 32;
-      52                 :          0 :             while (len > 0 && input[len - 1] == bytes1(0x00)) {
-      53                 :          0 :                 len--;
-      54                 :            :             }
-      55                 :            : 
-      56                 :          0 :             bytes memory inputTruncated = new bytes(len);
-      57                 :          0 :             for (uint8 i = 0; i < len; i++) {
-      58                 :          0 :                 inputTruncated[i] = input[i];
-      59                 :            :             }
-      60                 :            :             // we can't just do `res := input` because of the null values in the end
-      61                 :            :             // TODO: can we instead use a bitwise AND? build it dynamically with the length
-      62                 :            :             assembly {
-      63                 :          0 :                 res := inputTruncated
-      64                 :            :             }
-      65                 :            :         } else {
-      66                 :            :             // TODO: try catch to handle error
-      67                 :          0 :             success = true;
-      68                 :          0 :             res = abi.decode(input, (string));
-      69                 :            :         }
-      70                 :            :     }
-      71                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ClonableBeaconProxy.sol.func-sort-c.html b/coverage/libraries/ClonableBeaconProxy.sol.func-sort-c.html deleted file mode 100644 index 0c5732f7f1..0000000000 --- a/coverage/libraries/ClonableBeaconProxy.sol.func-sort-c.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ClonableBeaconProxy.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ClonableBeaconProxy.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
BeaconProxyFactory.calculateExpectedAddress0
BeaconProxyFactory.createProxy0
BeaconProxyFactory.getSalt0
BeaconProxyFactory.initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ClonableBeaconProxy.sol.func.html b/coverage/libraries/ClonableBeaconProxy.sol.func.html deleted file mode 100644 index 72ecebac19..0000000000 --- a/coverage/libraries/ClonableBeaconProxy.sol.func.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ClonableBeaconProxy.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ClonableBeaconProxy.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
BeaconProxyFactory.calculateExpectedAddress0
BeaconProxyFactory.createProxy0
BeaconProxyFactory.getSalt0
BeaconProxyFactory.initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ClonableBeaconProxy.sol.gcov.html b/coverage/libraries/ClonableBeaconProxy.sol.gcov.html deleted file mode 100644 index 1e581616e7..0000000000 --- a/coverage/libraries/ClonableBeaconProxy.sol.gcov.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ClonableBeaconProxy.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ClonableBeaconProxy.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : // solhint-disable-next-line compiler-version
-       3                 :            : pragma solidity >=0.6.0 <0.9.0;
-       4                 :            : 
-       5                 :            : import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
-       6                 :            : import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
-       7                 :            : import "@openzeppelin/contracts/utils/Create2.sol";
-       8                 :            : 
-       9                 :            : interface ProxySetter {
-      10                 :            :     function beacon() external view returns (address);
-      11                 :            : }
-      12                 :            : 
-      13                 :            : contract ClonableBeaconProxy is BeaconProxy {
-      14                 :            :     constructor() BeaconProxy(ProxySetter(msg.sender).beacon(), "") {}
-      15                 :            : }
-      16                 :            : 
-      17                 :            : contract BeaconProxyFactory is ProxySetter {
-      18                 :            :     bytes32 public constant cloneableProxyHash = keccak256(type(ClonableBeaconProxy).creationCode);
-      19                 :            : 
-      20                 :            :     /**
-      21                 :            :      * @notice utility function used in ClonableBeaconProxy.
-      22                 :            :      * @dev this method makes it possible to use ClonableBeaconProxy.creationCode without encoding constructor parameters
-      23                 :            :      * @return the beacon to be used by the proxy contract.
-      24                 :            :      */
-      25                 :            :     address public override beacon;
-      26                 :            : 
-      27                 :            :     function initialize(address _beacon) external {
-      28         [ #  # ]:          0 :         require(_beacon != address(0), "INVALID_BEACON");
-      29         [ #  # ]:          0 :         require(beacon == address(0), "ALREADY_INIT");
-      30                 :          0 :         beacon = _beacon;
-      31                 :            :     }
-      32                 :            : 
-      33                 :            :     function getSalt(address user, bytes32 userSalt) public pure returns (bytes32) {
-      34                 :          0 :         return keccak256(abi.encode(user, userSalt));
-      35                 :            :     }
-      36                 :            : 
-      37                 :            :     function createProxy(bytes32 userSalt) external returns (address) {
-      38                 :            :         // deployment will fail and this function will revert if contract `salt` is not unique
-      39                 :          0 :         bytes32 salt = getSalt(msg.sender, userSalt);
-      40                 :          0 :         address createdContract = address(new ClonableBeaconProxy{ salt: salt }());
-      41                 :          0 :         return createdContract;
-      42                 :            :     }
-      43                 :            : 
-      44                 :            :     function calculateExpectedAddress(address user, bytes32 userSalt)
-      45                 :            :         public
-      46                 :            :         view
-      47                 :            :         returns (address)
-      48                 :            :     {
-      49                 :          0 :         bytes32 salt = getSalt(user, userSalt);
-      50                 :          0 :         return Create2.computeAddress(salt, cloneableProxyHash, address(this));
-      51                 :            :     }
-      52                 :            : 
-      53                 :            :     function calculateExpectedAddress(bytes32 salt) public view returns (address) {
-      54                 :          0 :         return Create2.computeAddress(salt, cloneableProxyHash, address(this));
-      55                 :            :     }
-      56                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/Cloneable.sol.func-sort-c.html b/coverage/libraries/Cloneable.sol.func-sort-c.html deleted file mode 100644 index 68c91b8295..0000000000 --- a/coverage/libraries/Cloneable.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/Cloneable.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - Cloneable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
Cloneable.isMaster0
Cloneable.safeSelfDestruct0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/Cloneable.sol.func.html b/coverage/libraries/Cloneable.sol.func.html deleted file mode 100644 index c7986cc2d1..0000000000 --- a/coverage/libraries/Cloneable.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/Cloneable.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - Cloneable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
Cloneable.isMaster0
Cloneable.safeSelfDestruct0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/Cloneable.sol.gcov.html b/coverage/libraries/Cloneable.sol.gcov.html deleted file mode 100644 index e0cc61b704..0000000000 --- a/coverage/libraries/Cloneable.sol.gcov.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/Cloneable.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - Cloneable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:020.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2019-2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./ICloneable.sol";
-      22                 :            : 
-      23                 :            : contract Cloneable is ICloneable {
-      24                 :            :     string private constant NOT_CLONE = "NOT_CLONE";
-      25                 :            : 
-      26                 :            :     bool private isMasterCopy;
-      27                 :            : 
-      28                 :            :     constructor() {
-      29                 :            :         isMasterCopy = true;
-      30                 :            :     }
-      31                 :            : 
-      32                 :            :     function isMaster() external view override returns (bool) {
-      33                 :          0 :         return isMasterCopy;
-      34                 :            :     }
-      35                 :            : 
-      36                 :            :     function safeSelfDestruct(address payable dest) internal {
-      37         [ #  # ]:          0 :         require(!isMasterCopy, NOT_CLONE);
-      38                 :          0 :         selfdestruct(dest);
-      39                 :            :     }
-      40                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ERC165.sol.func-sort-c.html b/coverage/libraries/ERC165.sol.func-sort-c.html deleted file mode 100644 index 789dc60044..0000000000 --- a/coverage/libraries/ERC165.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ERC165.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ERC165.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ERC165.supportsInterface768
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ERC165.sol.func.html b/coverage/libraries/ERC165.sol.func.html deleted file mode 100644 index 85351d4658..0000000000 --- a/coverage/libraries/ERC165.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ERC165.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ERC165.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ERC165.supportsInterface768
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ERC165.sol.gcov.html b/coverage/libraries/ERC165.sol.gcov.html deleted file mode 100644 index d193de66ca..0000000000 --- a/coverage/libraries/ERC165.sol.gcov.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ERC165.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ERC165.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11100.0 %
Date:2023-04-27 16:26:32Functions:11100.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MIT
-       2                 :            : // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
-       3                 :            : 
-       4                 :            : // With pragma modification to support ^0.6.11
-       5                 :            : // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.6/contracts/utils/introspection/ERC165.sol
-       6                 :            : 
-       7                 :            : pragma solidity ^0.8.0;
-       8                 :            : 
-       9                 :            : import "./IERC165.sol";
-      10                 :            : 
-      11                 :            : /**
-      12                 :            :  * @dev Implementation of the {IERC165} interface.
-      13                 :            :  *
-      14                 :            :  * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
-      15                 :            :  * for the additional interface id that will be supported. For example:
-      16                 :            :  *
-      17                 :            :  * ```solidity
-      18                 :            :  * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
-      19                 :            :  *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
-      20                 :            :  * }
-      21                 :            :  * ```
-      22                 :            :  *
-      23                 :            :  * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
-      24                 :            :  */
-      25                 :            : abstract contract ERC165 is IERC165 {
-      26                 :            :     /**
-      27                 :            :      * @dev See {IERC165-supportsInterface}.
-      28                 :            :      */
-      29                 :            :     function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
-      30                 :        768 :         return interfaceId == type(IERC165).interfaceId;
-      31                 :            :     }
-      32                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ERC20Upgradeable.sol.func-sort-c.html b/coverage/libraries/ERC20Upgradeable.sol.func-sort-c.html deleted file mode 100644 index f38ddeb847..0000000000 --- a/coverage/libraries/ERC20Upgradeable.sol.func-sort-c.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ERC20Upgradeable.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ERC20Upgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:386063.3 %
Date:2023-04-27 16:26:32Functions:132161.9 %
Branches:102245.5 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ERC20Upgradeable.__ERC20_init0
ERC20Upgradeable.__ERC20_init_unchained0
ERC20Upgradeable._burn0
ERC20Upgradeable._setupDecimals0
ERC20Upgradeable.allowance0
ERC20Upgradeable.decreaseAllowance0
ERC20Upgradeable.increaseAllowance0
ERC20Upgradeable.totalSupply0
ERC20Upgradeable._mint2
ERC20Upgradeable.transfer2
ERC20Upgradeable.approve4
ERC20Upgradeable._spendAllowance6
ERC20Upgradeable._transfer6
ERC20Upgradeable.transferFrom6
ERC20Upgradeable._afterTokenTransfer8
ERC20Upgradeable._approve8
ERC20Upgradeable._beforeTokenTransfer8
ERC20Upgradeable.decimals10
ERC20Upgradeable.name10
ERC20Upgradeable.symbol10
ERC20Upgradeable.balanceOf34
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ERC20Upgradeable.sol.func.html b/coverage/libraries/ERC20Upgradeable.sol.func.html deleted file mode 100644 index ee1e8d493e..0000000000 --- a/coverage/libraries/ERC20Upgradeable.sol.func.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ERC20Upgradeable.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ERC20Upgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:386063.3 %
Date:2023-04-27 16:26:32Functions:132161.9 %
Branches:102245.5 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ERC20Upgradeable.__ERC20_init0
ERC20Upgradeable.__ERC20_init_unchained0
ERC20Upgradeable._afterTokenTransfer8
ERC20Upgradeable._approve8
ERC20Upgradeable._beforeTokenTransfer8
ERC20Upgradeable._burn0
ERC20Upgradeable._mint2
ERC20Upgradeable._setupDecimals0
ERC20Upgradeable._spendAllowance6
ERC20Upgradeable._transfer6
ERC20Upgradeable.allowance0
ERC20Upgradeable.approve4
ERC20Upgradeable.balanceOf34
ERC20Upgradeable.decimals10
ERC20Upgradeable.decreaseAllowance0
ERC20Upgradeable.increaseAllowance0
ERC20Upgradeable.name10
ERC20Upgradeable.symbol10
ERC20Upgradeable.totalSupply0
ERC20Upgradeable.transfer2
ERC20Upgradeable.transferFrom6
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ERC20Upgradeable.sol.gcov.html b/coverage/libraries/ERC20Upgradeable.sol.gcov.html deleted file mode 100644 index 4d64e14dee..0000000000 --- a/coverage/libraries/ERC20Upgradeable.sol.gcov.html +++ /dev/null @@ -1,477 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ERC20Upgradeable.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ERC20Upgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:386063.3 %
Date:2023-04-27 16:26:32Functions:132161.9 %
Branches:102245.5 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MIT
-       2                 :            : // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)
-       3                 :            : 
-       4                 :            : pragma solidity ^0.8.0;
-       5                 :            : 
-       6                 :            : import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
-       7                 :            : import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
-       8                 :            : import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
-       9                 :            : import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
-      10                 :            : 
-      11                 :            : /**
-      12                 :            :  * @dev Implementation of the {IERC20} interface.
-      13                 :            :  *
-      14                 :            :  * This implementation is based on OpenZeppelin implementation (https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.8.3/contracts/token/ERC20/ERC20Upgradeable.sol)
-      15                 :            :  * with a small modification. OZ implementation removed `decimals` storage variable when they did upgrade to Solidity 0.8. Since we're already using older OZ implementation, here we're
-      16                 :            :  * adding back the `decimals` storage variable along with the appropriate getter and setter. That way we avoid changes in storage layout that would've happen due to OZ removing token
-      17                 :            :  * decimals storage variable.
-      18                 :            :  *
-      19                 :            :  */
-      20                 :            : contract ERC20Upgradeable is
-      21                 :            :     Initializable,
-      22                 :            :     ContextUpgradeable,
-      23                 :            :     IERC20Upgradeable,
-      24                 :            :     IERC20MetadataUpgradeable
-      25                 :            : {
-      26                 :            :     mapping(address => uint256) private _balances;
-      27                 :            : 
-      28                 :            :     mapping(address => mapping(address => uint256)) private _allowances;
-      29                 :            : 
-      30                 :            :     uint256 private _totalSupply;
-      31                 :            : 
-      32                 :            :     string private _name;
-      33                 :            :     string private _symbol;
-      34                 :            :     uint8 private _decimals;
-      35                 :            : 
-      36                 :            :     /**
-      37                 :            :      * @dev Sets the values for {name} and {symbol}.
-      38                 :            :      *
-      39                 :            :      * The default value of {decimals} is 18. To select a different value for
-      40                 :            :      * {decimals} you should overload it.
-      41                 :            :      *
-      42                 :            :      * All two of these values are immutable: they can only be set once during
-      43                 :            :      * construction.
-      44                 :            :      */
-      45                 :            :     function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
-      46                 :          0 :         __ERC20_init_unchained(name_, symbol_);
-      47                 :            :     }
-      48                 :            : 
-      49                 :            :     function __ERC20_init_unchained(
-      50                 :            :         string memory name_,
-      51                 :            :         string memory symbol_
-      52                 :            :     ) internal onlyInitializing {
-      53                 :          0 :         _name = name_;
-      54                 :          0 :         _symbol = symbol_;
-      55                 :          0 :         _decimals = 18;
-      56                 :            :     }
-      57                 :            : 
-      58                 :            :     /**
-      59                 :            :      * @dev Returns the name of the token.
-      60                 :            :      */
-      61                 :            :     function name() public view virtual override returns (string memory) {
-      62                 :         10 :         return _name;
-      63                 :            :     }
-      64                 :            : 
-      65                 :            :     /**
-      66                 :            :      * @dev Returns the symbol of the token, usually a shorter version of the
-      67                 :            :      * name.
-      68                 :            :      */
-      69                 :            :     function symbol() public view virtual override returns (string memory) {
-      70                 :         10 :         return _symbol;
-      71                 :            :     }
-      72                 :            : 
-      73                 :            :     /**
-      74                 :            :      * @dev Returns the number of decimals used to get its user representation.
-      75                 :            :      * For example, if `decimals` equals `2`, a balance of `505` tokens should
-      76                 :            :      * be displayed to a user as `5.05` (`505 / 10 ** 2`).
-      77                 :            :      *
-      78                 :            :      * Tokens usually opt for a value of 18, imitating the relationship between
-      79                 :            :      * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
-      80                 :            :      * called;
-      81                 :            :      *
-      82                 :            :      * NOTE: This information is only used for _display_ purposes: it in
-      83                 :            :      * no way affects any of the arithmetic of the contract, including
-      84                 :            :      * {IERC20-balanceOf} and {IERC20-transfer}.
-      85                 :            :      */
-      86                 :            :     function decimals() public view virtual override returns (uint8) {
-      87                 :         10 :         return _decimals;
-      88                 :            :     }
-      89                 :            : 
-      90                 :            :     /**
-      91                 :            :      * @dev See {IERC20-totalSupply}.
-      92                 :            :      */
-      93                 :            :     function totalSupply() public view virtual override returns (uint256) {
-      94                 :          0 :         return _totalSupply;
-      95                 :            :     }
-      96                 :            : 
-      97                 :            :     /**
-      98                 :            :      * @dev See {IERC20-balanceOf}.
-      99                 :            :      */
-     100                 :            :     function balanceOf(address account) public view virtual override returns (uint256) {
-     101                 :         34 :         return _balances[account];
-     102                 :            :     }
-     103                 :            : 
-     104                 :            :     /**
-     105                 :            :      * @dev See {IERC20-transfer}.
-     106                 :            :      *
-     107                 :            :      * Requirements:
-     108                 :            :      *
-     109                 :            :      * - `to` cannot be the zero address.
-     110                 :            :      * - the caller must have a balance of at least `amount`.
-     111                 :            :      */
-     112                 :            :     function transfer(address to, uint256 amount) public virtual override returns (bool) {
-     113                 :          2 :         address owner = _msgSender();
-     114                 :          2 :         _transfer(owner, to, amount);
-     115                 :          2 :         return true;
-     116                 :            :     }
-     117                 :            : 
-     118                 :            :     /**
-     119                 :            :      * @dev See {IERC20-allowance}.
-     120                 :            :      */
-     121                 :            :     function allowance(
-     122                 :            :         address owner,
-     123                 :            :         address spender
-     124                 :            :     ) public view virtual override returns (uint256) {
-     125                 :          6 :         return _allowances[owner][spender];
-     126                 :            :     }
-     127                 :            : 
-     128                 :            :     /**
-     129                 :            :      * @dev See {IERC20-approve}.
-     130                 :            :      *
-     131                 :            :      * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
-     132                 :            :      * `transferFrom`. This is semantically equivalent to an infinite approval.
-     133                 :            :      *
-     134                 :            :      * Requirements:
-     135                 :            :      *
-     136                 :            :      * - `spender` cannot be the zero address.
-     137                 :            :      */
-     138                 :            :     function approve(address spender, uint256 amount) public virtual override returns (bool) {
-     139                 :          4 :         address owner = _msgSender();
-     140                 :          4 :         _approve(owner, spender, amount);
-     141                 :          4 :         return true;
-     142                 :            :     }
-     143                 :            : 
-     144                 :            :     /**
-     145                 :            :      * @dev See {IERC20-transferFrom}.
-     146                 :            :      *
-     147                 :            :      * Emits an {Approval} event indicating the updated allowance. This is not
-     148                 :            :      * required by the EIP. See the note at the beginning of {ERC20}.
-     149                 :            :      *
-     150                 :            :      * NOTE: Does not update the allowance if the current allowance
-     151                 :            :      * is the maximum `uint256`.
-     152                 :            :      *
-     153                 :            :      * Requirements:
-     154                 :            :      *
-     155                 :            :      * - `from` and `to` cannot be the zero address.
-     156                 :            :      * - `from` must have a balance of at least `amount`.
-     157                 :            :      * - the caller must have allowance for ``from``'s tokens of at least
-     158                 :            :      * `amount`.
-     159                 :            :      */
-     160                 :            :     function transferFrom(
-     161                 :            :         address from,
-     162                 :            :         address to,
-     163                 :            :         uint256 amount
-     164                 :            :     ) public virtual override returns (bool) {
-     165                 :          6 :         address spender = _msgSender();
-     166                 :          6 :         _spendAllowance(from, spender, amount);
-     167                 :          4 :         _transfer(from, to, amount);
-     168                 :          4 :         return true;
-     169                 :            :     }
-     170                 :            : 
-     171                 :            :     /**
-     172                 :            :      * @dev Atomically increases the allowance granted to `spender` by the caller.
-     173                 :            :      *
-     174                 :            :      * This is an alternative to {approve} that can be used as a mitigation for
-     175                 :            :      * problems described in {IERC20-approve}.
-     176                 :            :      *
-     177                 :            :      * Emits an {Approval} event indicating the updated allowance.
-     178                 :            :      *
-     179                 :            :      * Requirements:
-     180                 :            :      *
-     181                 :            :      * - `spender` cannot be the zero address.
-     182                 :            :      */
-     183                 :            :     function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
-     184                 :          0 :         address owner = _msgSender();
-     185                 :          0 :         _approve(owner, spender, allowance(owner, spender) + addedValue);
-     186                 :          0 :         return true;
-     187                 :            :     }
-     188                 :            : 
-     189                 :            :     /**
-     190                 :            :      * @dev Atomically decreases the allowance granted to `spender` by the caller.
-     191                 :            :      *
-     192                 :            :      * This is an alternative to {approve} that can be used as a mitigation for
-     193                 :            :      * problems described in {IERC20-approve}.
-     194                 :            :      *
-     195                 :            :      * Emits an {Approval} event indicating the updated allowance.
-     196                 :            :      *
-     197                 :            :      * Requirements:
-     198                 :            :      *
-     199                 :            :      * - `spender` cannot be the zero address.
-     200                 :            :      * - `spender` must have allowance for the caller of at least
-     201                 :            :      * `subtractedValue`.
-     202                 :            :      */
-     203                 :            :     function decreaseAllowance(
-     204                 :            :         address spender,
-     205                 :            :         uint256 subtractedValue
-     206                 :            :     ) public virtual returns (bool) {
-     207                 :          0 :         address owner = _msgSender();
-     208                 :          0 :         uint256 currentAllowance = allowance(owner, spender);
-     209         [ #  # ]:          0 :         require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
-     210                 :            :         unchecked {
-     211                 :          0 :             _approve(owner, spender, currentAllowance - subtractedValue);
-     212                 :            :         }
-     213                 :            : 
-     214                 :          0 :         return true;
-     215                 :            :     }
-     216                 :            : 
-     217                 :            :     /**
-     218                 :            :      * @dev Moves `amount` of tokens from `from` to `to`.
-     219                 :            :      *
-     220                 :            :      * This internal function is equivalent to {transfer}, and can be used to
-     221                 :            :      * e.g. implement automatic token fees, slashing mechanisms, etc.
-     222                 :            :      *
-     223                 :            :      * Emits a {Transfer} event.
-     224                 :            :      *
-     225                 :            :      * Requirements:
-     226                 :            :      *
-     227                 :            :      * - `from` cannot be the zero address.
-     228                 :            :      * - `to` cannot be the zero address.
-     229                 :            :      * - `from` must have a balance of at least `amount`.
-     230                 :            :      */
-     231                 :            :     function _transfer(address from, address to, uint256 amount) internal virtual {
-     232         [ #  + ]:          6 :         require(from != address(0), "ERC20: transfer from the zero address");
-     233         [ #  + ]:          6 :         require(to != address(0), "ERC20: transfer to the zero address");
-     234                 :            : 
-     235                 :          6 :         _beforeTokenTransfer(from, to, amount);
-     236                 :            : 
-     237                 :          6 :         uint256 fromBalance = _balances[from];
-     238         [ #  + ]:          6 :         require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
-     239                 :            :         unchecked {
-     240                 :          6 :             _balances[from] = fromBalance - amount;
-     241                 :            :             // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
-     242                 :            :             // decrementing then incrementing.
-     243                 :          6 :             _balances[to] += amount;
-     244                 :            :         }
-     245                 :            : 
-     246                 :          6 :         emit Transfer(from, to, amount);
-     247                 :            : 
-     248                 :          6 :         _afterTokenTransfer(from, to, amount);
-     249                 :            :     }
-     250                 :            : 
-     251                 :            :     /** @dev Creates `amount` tokens and assigns them to `account`, increasing
-     252                 :            :      * the total supply.
-     253                 :            :      *
-     254                 :            :      * Emits a {Transfer} event with `from` set to the zero address.
-     255                 :            :      *
-     256                 :            :      * Requirements:
-     257                 :            :      *
-     258                 :            :      * - `account` cannot be the zero address.
-     259                 :            :      */
-     260                 :            :     function _mint(address account, uint256 amount) internal virtual {
-     261         [ #  + ]:          2 :         require(account != address(0), "ERC20: mint to the zero address");
-     262                 :            : 
-     263                 :          2 :         _beforeTokenTransfer(address(0), account, amount);
-     264                 :            : 
-     265                 :          2 :         _totalSupply += amount;
-     266                 :            :         unchecked {
-     267                 :            :             // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
-     268                 :          2 :             _balances[account] += amount;
-     269                 :            :         }
-     270                 :          2 :         emit Transfer(address(0), account, amount);
-     271                 :            : 
-     272                 :          2 :         _afterTokenTransfer(address(0), account, amount);
-     273                 :            :     }
-     274                 :            : 
-     275                 :            :     /**
-     276                 :            :      * @dev Destroys `amount` tokens from `account`, reducing the
-     277                 :            :      * total supply.
-     278                 :            :      *
-     279                 :            :      * Emits a {Transfer} event with `to` set to the zero address.
-     280                 :            :      *
-     281                 :            :      * Requirements:
-     282                 :            :      *
-     283                 :            :      * - `account` cannot be the zero address.
-     284                 :            :      * - `account` must have at least `amount` tokens.
-     285                 :            :      */
-     286                 :            :     function _burn(address account, uint256 amount) internal virtual {
-     287         [ #  # ]:          0 :         require(account != address(0), "ERC20: burn from the zero address");
-     288                 :            : 
-     289                 :          0 :         _beforeTokenTransfer(account, address(0), amount);
-     290                 :            : 
-     291                 :          0 :         uint256 accountBalance = _balances[account];
-     292         [ #  # ]:          0 :         require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
-     293                 :            :         unchecked {
-     294                 :          0 :             _balances[account] = accountBalance - amount;
-     295                 :            :             // Overflow not possible: amount <= accountBalance <= totalSupply.
-     296                 :          0 :             _totalSupply -= amount;
-     297                 :            :         }
-     298                 :            : 
-     299                 :          0 :         emit Transfer(account, address(0), amount);
-     300                 :            : 
-     301                 :          0 :         _afterTokenTransfer(account, address(0), amount);
-     302                 :            :     }
-     303                 :            : 
-     304                 :            :     /**
-     305                 :            :      * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
-     306                 :            :      *
-     307                 :            :      * This internal function is equivalent to `approve`, and can be used to
-     308                 :            :      * e.g. set automatic allowances for certain subsystems, etc.
-     309                 :            :      *
-     310                 :            :      * Emits an {Approval} event.
-     311                 :            :      *
-     312                 :            :      * Requirements:
-     313                 :            :      *
-     314                 :            :      * - `owner` cannot be the zero address.
-     315                 :            :      * - `spender` cannot be the zero address.
-     316                 :            :      */
-     317                 :            :     function _approve(address owner, address spender, uint256 amount) internal virtual {
-     318         [ #  + ]:          8 :         require(owner != address(0), "ERC20: approve from the zero address");
-     319         [ #  + ]:          8 :         require(spender != address(0), "ERC20: approve to the zero address");
-     320                 :            : 
-     321                 :          8 :         _allowances[owner][spender] = amount;
-     322                 :          8 :         emit Approval(owner, spender, amount);
-     323                 :            :     }
-     324                 :            : 
-     325                 :            :     /**
-     326                 :            :      * @dev Sets {decimals} to a value other than the default one of 18.
-     327                 :            :      *
-     328                 :            :      * WARNING: This function should only be called from the constructor. Most
-     329                 :            :      * applications that interact with token contracts will not expect
-     330                 :            :      * {decimals} to ever change, and may work incorrectly if it does.
-     331                 :            :      */
-     332                 :            :     function _setupDecimals(uint8 decimals_) internal virtual {
-     333                 :          0 :         _decimals = decimals_;
-     334                 :            :     }
-     335                 :            : 
-     336                 :            :     /**
-     337                 :            :      * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
-     338                 :            :      *
-     339                 :            :      * Does not update the allowance amount in case of infinite allowance.
-     340                 :            :      * Revert if not enough allowance is available.
-     341                 :            :      *
-     342                 :            :      * Might emit an {Approval} event.
-     343                 :            :      */
-     344                 :            :     function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
-     345                 :          6 :         uint256 currentAllowance = allowance(owner, spender);
-     346         [ +  + ]:          6 :         if (currentAllowance != type(uint256).max) {
-     347         [ +  + ]:          6 :             require(currentAllowance >= amount, "ERC20: insufficient allowance");
-     348                 :            :             unchecked {
-     349                 :          4 :                 _approve(owner, spender, currentAllowance - amount);
-     350                 :            :             }
-     351                 :            :         }
-     352                 :            :     }
-     353                 :            : 
-     354                 :            :     /**
-     355                 :            :      * @dev Hook that is called before any transfer of tokens. This includes
-     356                 :            :      * minting and burning.
-     357                 :            :      *
-     358                 :            :      * Calling conditions:
-     359                 :            :      *
-     360                 :            :      * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
-     361                 :            :      * will be transferred to `to`.
-     362                 :            :      * - when `from` is zero, `amount` tokens will be minted for `to`.
-     363                 :            :      * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
-     364                 :            :      * - `from` and `to` are never both zero.
-     365                 :            :      *
-     366                 :            :      * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
-     367                 :            :      */
-     368                 :            :     function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
-     369                 :            : 
-     370                 :            :     /**
-     371                 :            :      * @dev Hook that is called after any transfer of tokens. This includes
-     372                 :            :      * minting and burning.
-     373                 :            :      *
-     374                 :            :      * Calling conditions:
-     375                 :            :      *
-     376                 :            :      * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
-     377                 :            :      * has been transferred to `to`.
-     378                 :            :      * - when `from` is zero, `amount` tokens have been minted for `to`.
-     379                 :            :      * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
-     380                 :            :      * - `from` and `to` are never both zero.
-     381                 :            :      *
-     382                 :            :      * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
-     383                 :            :      */
-     384                 :            :     function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
-     385                 :            : 
-     386                 :            :     /**
-     387                 :            :      * @dev This empty reserved space is put in place to allow future versions to add new
-     388                 :            :      * variables without shifting down storage in the inheritance chain.
-     389                 :            :      * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
-     390                 :            :      */
-     391                 :            :     uint256[44] private __gap;
-     392                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/L2CustomGatewayToken.sol.func-sort-c.html b/coverage/libraries/L2CustomGatewayToken.sol.func-sort-c.html deleted file mode 100644 index b4eed9ebdc..0000000000 --- a/coverage/libraries/L2CustomGatewayToken.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/L2CustomGatewayToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - L2CustomGatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2CustomGatewayToken.initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/L2CustomGatewayToken.sol.func.html b/coverage/libraries/L2CustomGatewayToken.sol.func.html deleted file mode 100644 index ef4c2db67a..0000000000 --- a/coverage/libraries/L2CustomGatewayToken.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/L2CustomGatewayToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - L2CustomGatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2CustomGatewayToken.initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/L2CustomGatewayToken.sol.gcov.html b/coverage/libraries/L2CustomGatewayToken.sol.gcov.html deleted file mode 100644 index fb5554bb3e..0000000000 --- a/coverage/libraries/L2CustomGatewayToken.sol.gcov.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/L2CustomGatewayToken.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - L2CustomGatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./L2GatewayToken.sol";
-      22                 :            : 
-      23                 :            : /**
-      24                 :            :  * @title A basic custom token contract that can be used with the custom gateway
-      25                 :            :  */
-      26                 :            : contract L2CustomGatewayToken is L2GatewayToken {
-      27                 :            :     /**
-      28                 :            :      * @notice initialize the token
-      29                 :            :      * @dev the L2 bridge assumes this does not fail or revert
-      30                 :            :      * @param name_ ERC20 token name
-      31                 :            :      * @param symbol_ ERC20 token symbol
-      32                 :            :      * @param decimals_ ERC20 decimals
-      33                 :            :      * @param l2Gateway_ L2 gateway this token communicates with
-      34                 :            :      * @param l1Counterpart_ L1 address of ERC20
-      35                 :            :      */
-      36                 :            :     function initialize(
-      37                 :            :         string memory name_,
-      38                 :            :         string memory symbol_,
-      39                 :            :         uint8 decimals_,
-      40                 :            :         address l2Gateway_,
-      41                 :            :         address l1Counterpart_
-      42                 :            :     ) public virtual initializer {
-      43                 :          0 :         _initialize(name_, symbol_, decimals_, l2Gateway_, l1Counterpart_);
-      44                 :            :     }
-      45                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/L2GatewayToken.sol.func-sort-c.html b/coverage/libraries/L2GatewayToken.sol.func-sort-c.html deleted file mode 100644 index 320d3020db..0000000000 --- a/coverage/libraries/L2GatewayToken.sol.func-sort-c.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/L2GatewayToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - L2GatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2GatewayToken._initialize0
L2GatewayToken.bridgeBurn0
L2GatewayToken.bridgeMint0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/L2GatewayToken.sol.func.html b/coverage/libraries/L2GatewayToken.sol.func.html deleted file mode 100644 index 4332ed4944..0000000000 --- a/coverage/libraries/L2GatewayToken.sol.func.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/L2GatewayToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - L2GatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2GatewayToken._initialize0
L2GatewayToken.bridgeBurn0
L2GatewayToken.bridgeMint0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/L2GatewayToken.sol.gcov.html b/coverage/libraries/L2GatewayToken.sol.gcov.html deleted file mode 100644 index fc000103bd..0000000000 --- a/coverage/libraries/L2GatewayToken.sol.gcov.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/L2GatewayToken.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - L2GatewayToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:070.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:040.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./aeERC20.sol";
-      22                 :            : import "./BytesParser.sol";
-      23                 :            : import "../arbitrum/IArbToken.sol";
-      24                 :            : 
-      25                 :            : /**
-      26                 :            :  * @title Standard (i.e., non-custom) contract used as a base for different L2 Gateways
-      27                 :            :  */
-      28                 :            : abstract contract L2GatewayToken is aeERC20, IArbToken {
-      29                 :            :     address public l2Gateway;
-      30                 :            :     address public override l1Address;
-      31                 :            : 
-      32                 :            :     modifier onlyGateway() {
-      33                 :            :         require(msg.sender == l2Gateway, "ONLY_GATEWAY");
-      34                 :            :         _;
-      35                 :            :     }
-      36                 :            : 
-      37                 :            :     /**
-      38                 :            :      * @notice initialize the token
-      39                 :            :      * @dev the L2 bridge assumes this does not fail or revert
-      40                 :            :      * @param name_ ERC20 token name
-      41                 :            :      * @param symbol_ ERC20 token symbol
-      42                 :            :      * @param decimals_ ERC20 decimals
-      43                 :            :      * @param l2Gateway_ L2 gateway this token communicates with
-      44                 :            :      * @param l1Counterpart_ L1 address of ERC20
-      45                 :            :      */
-      46                 :            :     function _initialize(
-      47                 :            :         string memory name_,
-      48                 :            :         string memory symbol_,
-      49                 :            :         uint8 decimals_,
-      50                 :            :         address l2Gateway_,
-      51                 :            :         address l1Counterpart_
-      52                 :            :     ) internal virtual {
-      53         [ #  # ]:          0 :         require(l2Gateway_ != address(0), "INVALID_GATEWAY");
-      54         [ #  # ]:          0 :         require(l2Gateway == address(0), "ALREADY_INIT");
-      55                 :          0 :         l2Gateway = l2Gateway_;
-      56                 :          0 :         l1Address = l1Counterpart_;
-      57                 :            : 
-      58                 :          0 :         aeERC20._initialize(name_, symbol_, decimals_);
-      59                 :            :     }
-      60                 :            : 
-      61                 :            :     /**
-      62                 :            :      * @notice Mint tokens on L2. Callable path is L1Gateway depositToken (which handles L1 escrow), which triggers L2Gateway, which calls this
-      63                 :            :      * @param account recipient of tokens
-      64                 :            :      * @param amount amount of tokens minted
-      65                 :            :      */
-      66                 :            :     function bridgeMint(address account, uint256 amount) external virtual override onlyGateway {
-      67                 :          0 :         _mint(account, amount);
-      68                 :            :     }
-      69                 :            : 
-      70                 :            :     /**
-      71                 :            :      * @notice Burn tokens on L2.
-      72                 :            :      * @dev only the token bridge can call this
-      73                 :            :      * @param account owner of tokens
-      74                 :            :      * @param amount amount of tokens burnt
-      75                 :            :      */
-      76                 :            :     function bridgeBurn(address account, uint256 amount) external virtual override onlyGateway {
-      77                 :          0 :         _burn(account, amount);
-      78                 :            :     }
-      79                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ProxyUtil.sol.func-sort-c.html b/coverage/libraries/ProxyUtil.sol.func-sort-c.html deleted file mode 100644 index cbf0b9e395..0000000000 --- a/coverage/libraries/ProxyUtil.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ProxyUtil.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ProxyUtil.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ProxyUtil.getProxyAdmin0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ProxyUtil.sol.func.html b/coverage/libraries/ProxyUtil.sol.func.html deleted file mode 100644 index cb2720bb8e..0000000000 --- a/coverage/libraries/ProxyUtil.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ProxyUtil.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ProxyUtil.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ProxyUtil.getProxyAdmin0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/ProxyUtil.sol.gcov.html b/coverage/libraries/ProxyUtil.sol.gcov.html deleted file mode 100644 index 6276f6746f..0000000000 --- a/coverage/libraries/ProxyUtil.sol.gcov.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/ProxyUtil.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - ProxyUtil.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : library ProxyUtil {
-      22                 :            :     function getProxyAdmin() internal view returns (address admin) {
-      23                 :            :         // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/proxy/TransparentUpgradeableProxy.sol#L48
-      24                 :            :         // Storage slot with the admin of the proxy contract.
-      25                 :            :         // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
-      26                 :          0 :         bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
-      27                 :            :         assembly {
-      28                 :          0 :             admin := sload(slot)
-      29                 :            :         }
-      30                 :            :     }
-      31                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/TransferAndCallToken.sol.func-sort-c.html b/coverage/libraries/TransferAndCallToken.sol.func-sort-c.html deleted file mode 100644 index 5be6e1f45d..0000000000 --- a/coverage/libraries/TransferAndCallToken.sol.func-sort-c.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/TransferAndCallToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - TransferAndCallToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TransferAndCallToken.contractFallback0
TransferAndCallToken.isContract0
TransferAndCallToken.transferAndCall0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/TransferAndCallToken.sol.func.html b/coverage/libraries/TransferAndCallToken.sol.func.html deleted file mode 100644 index c7246bb1a2..0000000000 --- a/coverage/libraries/TransferAndCallToken.sol.func.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/TransferAndCallToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - TransferAndCallToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TransferAndCallToken.contractFallback0
TransferAndCallToken.isContract0
TransferAndCallToken.transferAndCall0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/TransferAndCallToken.sol.gcov.html b/coverage/libraries/TransferAndCallToken.sol.gcov.html deleted file mode 100644 index 2c301300f5..0000000000 --- a/coverage/libraries/TransferAndCallToken.sol.gcov.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/TransferAndCallToken.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - TransferAndCallToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0100.0 %
Date:2023-04-27 16:26:32Functions:030.0 %
Branches:020.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MIT
-       2                 :            : // solhint-disable-next-line compiler-version
-       3                 :            : pragma solidity >0.6.0 <0.9.0;
-       4                 :            : 
-       5                 :            : import "./ERC20Upgradeable.sol";
-       6                 :            : import "./ITransferAndCall.sol";
-       7                 :            : 
-       8                 :            : // Implementation from https://github.com/smartcontractkit/LinkToken/blob/master/contracts/v0.6/TransferAndCallToken.sol
-       9                 :            : /**
-      10                 :            :  * @notice based on Implementation from https://github.com/smartcontractkit/LinkToken/blob/master/contracts/v0.6/ERC677Token.sol
-      11                 :            :  * The implementation doesn't return a bool on onTokenTransfer. This is similar to the proposed 677 standard, but still incompatible - thus we don't refer to it as such.
-      12                 :            :  */
-      13                 :            : abstract contract TransferAndCallToken is ERC20Upgradeable, ITransferAndCall {
-      14                 :            :     /**
-      15                 :            :      * @dev transfer token to a contract address with additional data if the recipient is a contact.
-      16                 :            :      * @param _to The address to transfer to.
-      17                 :            :      * @param _value The amount to be transferred.
-      18                 :            :      * @param _data The extra data to be passed to the receiving contract.
-      19                 :            :      */
-      20                 :            :     function transferAndCall(
-      21                 :            :         address _to,
-      22                 :            :         uint256 _value,
-      23                 :            :         bytes memory _data
-      24                 :            :     ) public virtual override returns (bool success) {
-      25                 :          0 :         super.transfer(_to, _value);
-      26                 :          0 :         emit Transfer(msg.sender, _to, _value, _data);
-      27         [ #  # ]:          0 :         if (isContract(_to)) {
-      28                 :          0 :             contractFallback(_to, _value, _data);
-      29                 :            :         }
-      30                 :          0 :         return true;
-      31                 :            :     }
-      32                 :            : 
-      33                 :            :     // PRIVATE
-      34                 :            : 
-      35                 :            :     function contractFallback(
-      36                 :            :         address _to,
-      37                 :            :         uint256 _value,
-      38                 :            :         bytes memory _data
-      39                 :            :     ) private {
-      40                 :          0 :         ITransferAndCallReceiver receiver = ITransferAndCallReceiver(_to);
-      41                 :          0 :         receiver.onTokenTransfer(msg.sender, _value, _data);
-      42                 :            :     }
-      43                 :            : 
-      44                 :            :     function isContract(address _addr) private view returns (bool hasCode) {
-      45                 :          0 :         uint256 length;
-      46                 :            :         assembly {
-      47                 :          0 :             length := extcodesize(_addr)
-      48                 :            :         }
-      49                 :          0 :         return length > 0;
-      50                 :            :     }
-      51                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/Whitelist.sol.func-sort-c.html b/coverage/libraries/Whitelist.sol.func-sort-c.html deleted file mode 100644 index 3141a218fa..0000000000 --- a/coverage/libraries/Whitelist.sol.func-sort-c.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/Whitelist.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - Whitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
Whitelist.setOwner0
Whitelist.setWhitelist0
Whitelist.triggerConsumers0
WhitelistConsumer.updateWhitelistSource0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/Whitelist.sol.func.html b/coverage/libraries/Whitelist.sol.func.html deleted file mode 100644 index 065adddc61..0000000000 --- a/coverage/libraries/Whitelist.sol.func.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/Whitelist.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - Whitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
Whitelist.setOwner0
Whitelist.setWhitelist0
Whitelist.triggerConsumers0
WhitelistConsumer.updateWhitelistSource0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/Whitelist.sol.gcov.html b/coverage/libraries/Whitelist.sol.gcov.html deleted file mode 100644 index 99a9ebc96c..0000000000 --- a/coverage/libraries/Whitelist.sol.gcov.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/Whitelist.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - Whitelist.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:040.0 %
Branches:040.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : abstract contract WhitelistConsumer {
-      22                 :            :     address public whitelist;
-      23                 :            : 
-      24                 :            :     event WhitelistSourceUpdated(address newSource);
-      25                 :            : 
-      26                 :            :     modifier onlyWhitelisted() {
-      27                 :            :         if (whitelist != address(0)) {
-      28                 :            :             require(Whitelist(whitelist).isAllowed(msg.sender), "NOT_WHITELISTED");
-      29                 :            :         }
-      30                 :            :         _;
-      31                 :            :     }
-      32                 :            : 
-      33                 :            :     function updateWhitelistSource(address newSource) external {
-      34         [ #  # ]:          0 :         require(msg.sender == whitelist, "NOT_FROM_LIST");
-      35                 :          0 :         whitelist = newSource;
-      36                 :          0 :         emit WhitelistSourceUpdated(newSource);
-      37                 :            :     }
-      38                 :            : }
-      39                 :            : 
-      40                 :            : contract Whitelist {
-      41                 :            :     address public owner;
-      42                 :            :     mapping(address => bool) public isAllowed;
-      43                 :            : 
-      44                 :            :     event OwnerUpdated(address newOwner);
-      45                 :            :     event WhitelistUpgraded(address newWhitelist, address[] targets);
-      46                 :            : 
-      47                 :            :     constructor() {
-      48                 :            :         owner = msg.sender;
-      49                 :            :     }
-      50                 :            : 
-      51                 :            :     modifier onlyOwner() {
-      52                 :            :         require(msg.sender == owner, "ONLY_OWNER");
-      53                 :            :         _;
-      54                 :            :     }
-      55                 :            : 
-      56                 :            :     function setOwner(address newOwner) external onlyOwner {
-      57                 :          0 :         owner = newOwner;
-      58                 :          0 :         emit OwnerUpdated(newOwner);
-      59                 :            :     }
-      60                 :            : 
-      61                 :            :     function setWhitelist(address[] memory user, bool[] memory val) external onlyOwner {
-      62         [ #  # ]:          0 :         require(user.length == val.length, "INVALID_INPUT");
-      63                 :            : 
-      64                 :          0 :         for (uint256 i = 0; i < user.length; i++) {
-      65                 :          0 :             isAllowed[user[i]] = val[i];
-      66                 :            :         }
-      67                 :            :     }
-      68                 :            : 
-      69                 :            :     // set new whitelist to address(0) to disable whitelist
-      70                 :            :     function triggerConsumers(address newWhitelist, address[] memory targets) external onlyOwner {
-      71                 :          0 :         for (uint256 i = 0; i < targets.length; i++) {
-      72                 :          0 :             WhitelistConsumer(targets[i]).updateWhitelistSource(newWhitelist);
-      73                 :            :         }
-      74                 :          0 :         emit WhitelistUpgraded(newWhitelist, targets);
-      75                 :            :     }
-      76                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/aeERC20.sol.func-sort-c.html b/coverage/libraries/aeERC20.sol.func-sort-c.html deleted file mode 100644 index df6763dec5..0000000000 --- a/coverage/libraries/aeERC20.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/aeERC20.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - aeERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
aeERC20._initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/aeERC20.sol.func.html b/coverage/libraries/aeERC20.sol.func.html deleted file mode 100644 index 43a24228c2..0000000000 --- a/coverage/libraries/aeERC20.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/aeERC20.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - aeERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
aeERC20._initialize0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/aeERC20.sol.gcov.html b/coverage/libraries/aeERC20.sol.gcov.html deleted file mode 100644 index 840ac6b19f..0000000000 --- a/coverage/libraries/aeERC20.sol.gcov.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/aeERC20.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - aeERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../libraries/draft-ERC20PermitUpgradeable.sol";
-      22                 :            : import "./TransferAndCallToken.sol";
-      23                 :            : 
-      24                 :            : /// @title Arbitrum extended ERC20
-      25                 :            : /// @notice The recommended ERC20 implementation for Layer 2 tokens
-      26                 :            : /// @dev This implements the ERC20 standard with transferAndCall extenstion/affordances
-      27                 :            : contract aeERC20 is ERC20PermitUpgradeable, TransferAndCallToken {
-      28                 :            :     using AddressUpgradeable for address;
-      29                 :            : 
-      30                 :            :     constructor() initializer {
-      31                 :            :         // this is expected to be used as the logic contract behind a proxy
-      32                 :            :         // override the constructor if you don't wish to use the initialize method
-      33                 :            :     }
-      34                 :            : 
-      35                 :            :     function _initialize(
-      36                 :            :         string memory name_,
-      37                 :            :         string memory symbol_,
-      38                 :            :         uint8 decimals_
-      39                 :            :     ) internal initializer {
-      40                 :          0 :         __ERC20Permit_init(name_);
-      41                 :          0 :         __ERC20_init(name_, symbol_);
-      42                 :          0 :         _setupDecimals(decimals_);
-      43                 :            :     }
-      44                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/aeWETH.sol.func-sort-c.html b/coverage/libraries/aeWETH.sol.func-sort-c.html deleted file mode 100644 index db4b6adcb0..0000000000 --- a/coverage/libraries/aeWETH.sol.func-sort-c.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/aeWETH.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - aeWETH.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
aeWETH.bridgeBurn0
aeWETH.bridgeMint0
aeWETH.deposit0
aeWETH.depositTo0
aeWETH.initialize0
aeWETH.withdraw0
aeWETH.withdrawTo0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/aeWETH.sol.func.html b/coverage/libraries/aeWETH.sol.func.html deleted file mode 100644 index f4346e3b47..0000000000 --- a/coverage/libraries/aeWETH.sol.func.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/aeWETH.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - aeWETH.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
aeWETH.bridgeBurn0
aeWETH.bridgeMint0
aeWETH.deposit0
aeWETH.depositTo0
aeWETH.initialize0
aeWETH.withdraw0
aeWETH.withdrawTo0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/aeWETH.sol.gcov.html b/coverage/libraries/aeWETH.sol.gcov.html deleted file mode 100644 index 80ee708be1..0000000000 --- a/coverage/libraries/aeWETH.sol.gcov.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/aeWETH.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - aeWETH.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0110.0 %
Date:2023-04-27 16:26:32Functions:070.0 %
Branches:040.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./L2GatewayToken.sol";
-      22                 :            : import "./IWETH9.sol";
-      23                 :            : 
-      24                 :            : /// @title Arbitrum extended WETH
-      25                 :            : contract aeWETH is L2GatewayToken, IWETH9 {
-      26                 :            :     function initialize(
-      27                 :            :         string memory name_,
-      28                 :            :         string memory symbol_,
-      29                 :            :         uint8 decimals_,
-      30                 :            :         address l2Gateway_,
-      31                 :            :         address l1Address_
-      32                 :            :     ) external {
-      33                 :          0 :         L2GatewayToken._initialize(name_, symbol_, decimals_, l2Gateway_, l1Address_);
-      34                 :            :     }
-      35                 :            : 
-      36                 :            :     function bridgeMint(
-      37                 :            :         address, /* account */
-      38                 :            :         uint256 /* amount */
-      39                 :            :     ) external virtual override {
-      40                 :            :         // we want weth to always be fully collaterized
-      41                 :          0 :         revert("NO_BRIDGE_MINT");
-      42                 :            :     }
-      43                 :            : 
-      44                 :            :     function bridgeBurn(address account, uint256 amount) external virtual override onlyGateway {
-      45                 :          0 :         _burn(account, amount);
-      46                 :          0 :         (bool success, ) = msg.sender.call{ value: amount }("");
-      47         [ #  # ]:          0 :         require(success, "FAIL_TRANSFER");
-      48                 :            :     }
-      49                 :            : 
-      50                 :            :     function deposit() external payable override {
-      51                 :          0 :         depositTo(msg.sender);
-      52                 :            :     }
-      53                 :            : 
-      54                 :            :     function withdraw(uint256 amount) external override {
-      55                 :          0 :         withdrawTo(msg.sender, amount);
-      56                 :            :     }
-      57                 :            : 
-      58                 :            :     function depositTo(address account) public payable {
-      59                 :          0 :         _mint(account, msg.value);
-      60                 :            :     }
-      61                 :            : 
-      62                 :            :     function withdrawTo(address account, uint256 amount) public {
-      63                 :          0 :         _burn(msg.sender, amount);
-      64                 :          0 :         (bool success, ) = account.call{ value: amount }("");
-      65         [ #  # ]:          0 :         require(success, "FAIL_TRANSFER");
-      66                 :            :     }
-      67                 :            : 
-      68                 :            :     receive() external payable {
-      69                 :            :         depositTo(msg.sender);
-      70                 :            :     }
-      71                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func-sort-c.html b/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func-sort-c.html deleted file mode 100644 index 2b6431a5a8..0000000000 --- a/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func-sort-c.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/draft-ERC20PermitUpgradeable.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - draft-ERC20PermitUpgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ERC20PermitUpgradeable.DOMAIN_SEPARATOR0
ERC20PermitUpgradeable.__ERC20Permit_init0
ERC20PermitUpgradeable.__ERC20Permit_init_unchained0
ERC20PermitUpgradeable._useNonce0
ERC20PermitUpgradeable.nonces0
ERC20PermitUpgradeable.permit0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func.html b/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func.html deleted file mode 100644 index 72c3cf268a..0000000000 --- a/coverage/libraries/draft-ERC20PermitUpgradeable.sol.func.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/draft-ERC20PermitUpgradeable.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - draft-ERC20PermitUpgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:040.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ERC20PermitUpgradeable.DOMAIN_SEPARATOR0
ERC20PermitUpgradeable.__ERC20Permit_init0
ERC20PermitUpgradeable.__ERC20Permit_init_unchained0
ERC20PermitUpgradeable._useNonce0
ERC20PermitUpgradeable.nonces0
ERC20PermitUpgradeable.permit0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/draft-ERC20PermitUpgradeable.sol.gcov.html b/coverage/libraries/draft-ERC20PermitUpgradeable.sol.gcov.html deleted file mode 100644 index 848e81f72a..0000000000 --- a/coverage/libraries/draft-ERC20PermitUpgradeable.sol.gcov.html +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/draft-ERC20PermitUpgradeable.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries - draft-ERC20PermitUpgradeable.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0120.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:040.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: MIT
-       2                 :            : // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/extensions/draft-ERC20Permit.sol)
-       3                 :            : 
-       4                 :            : pragma solidity ^0.8.0;
-       5                 :            : 
-       6                 :            : import "./ERC20Upgradeable.sol";
-       7                 :            : import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol";
-       8                 :            : import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol";
-       9                 :            : import "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol";
-      10                 :            : import "@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol";
-      11                 :            : import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
-      12                 :            : 
-      13                 :            : /**
-      14                 :            :  * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
-      15                 :            :  * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
-      16                 :            :  *
-      17                 :            :  * This implementation is based on OpenZeppelin implementation (https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.8.3/contracts/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol).
-      18                 :            :  * The only difference is that we are importing our own `ERC20Upgradeable` implementation instead of the OpenZeppelin's one.
-      19                 :            :  *
-      20                 :            :  */
-      21                 :            : abstract contract ERC20PermitUpgradeable is
-      22                 :            :     Initializable,
-      23                 :            :     ERC20Upgradeable,
-      24                 :            :     IERC20PermitUpgradeable,
-      25                 :            :     EIP712Upgradeable
-      26                 :            : {
-      27                 :            :     using CountersUpgradeable for CountersUpgradeable.Counter;
-      28                 :            : 
-      29                 :            :     mapping(address => CountersUpgradeable.Counter) private _nonces;
-      30                 :            : 
-      31                 :            :     // solhint-disable-next-line var-name-mixedcase
-      32                 :            :     bytes32 private constant _PERMIT_TYPEHASH =
-      33                 :            :         keccak256(
-      34                 :            :             "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
-      35                 :            :         );
-      36                 :            :     /**
-      37                 :            :      * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`.
-      38                 :            :      * However, to ensure consistency with the upgradeable transpiler, we will continue
-      39                 :            :      * to reserve a slot.
-      40                 :            :      * @custom:oz-renamed-from _PERMIT_TYPEHASH
-      41                 :            :      */
-      42                 :            :     // solhint-disable-next-line var-name-mixedcase
-      43                 :            :     bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;
-      44                 :            : 
-      45                 :            :     /**
-      46                 :            :      * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
-      47                 :            :      *
-      48                 :            :      * It's a good idea to use the same `name` that is defined as the ERC20 token name.
-      49                 :            :      */
-      50                 :            :     function __ERC20Permit_init(string memory name) internal onlyInitializing {
-      51                 :          0 :         __EIP712_init_unchained(name, "1");
-      52                 :            :     }
-      53                 :            : 
-      54                 :            :     function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {}
-      55                 :            : 
-      56                 :            :     /**
-      57                 :            :      * @dev See {IERC20Permit-permit}.
-      58                 :            :      */
-      59                 :            :     function permit(
-      60                 :            :         address owner,
-      61                 :            :         address spender,
-      62                 :            :         uint256 value,
-      63                 :            :         uint256 deadline,
-      64                 :            :         uint8 v,
-      65                 :            :         bytes32 r,
-      66                 :            :         bytes32 s
-      67                 :            :     ) public virtual override {
-      68         [ #  # ]:          0 :         require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
-      69                 :            : 
-      70                 :          0 :         bytes32 structHash = keccak256(
-      71                 :            :             abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)
-      72                 :            :         );
-      73                 :            : 
-      74                 :          0 :         bytes32 hash = _hashTypedDataV4(structHash);
-      75                 :            : 
-      76                 :          0 :         address signer = ECDSAUpgradeable.recover(hash, v, r, s);
-      77         [ #  # ]:          0 :         require(signer == owner, "ERC20Permit: invalid signature");
-      78                 :            : 
-      79                 :          0 :         _approve(owner, spender, value);
-      80                 :            :     }
-      81                 :            : 
-      82                 :            :     /**
-      83                 :            :      * @dev See {IERC20Permit-nonces}.
-      84                 :            :      */
-      85                 :            :     function nonces(address owner) public view virtual override returns (uint256) {
-      86                 :          0 :         return _nonces[owner].current();
-      87                 :            :     }
-      88                 :            : 
-      89                 :            :     /**
-      90                 :            :      * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
-      91                 :            :      */
-      92                 :            :     // solhint-disable-next-line func-name-mixedcase
-      93                 :            :     function DOMAIN_SEPARATOR() external view override returns (bytes32) {
-      94                 :          0 :         return _domainSeparatorV4();
-      95                 :            :     }
-      96                 :            : 
-      97                 :            :     /**
-      98                 :            :      * @dev "Consume a nonce": return the current value and increment.
-      99                 :            :      *
-     100                 :            :      * _Available since v4.1._
-     101                 :            :      */
-     102                 :            :     function _useNonce(address owner) internal virtual returns (uint256 current) {
-     103                 :          0 :         CountersUpgradeable.Counter storage nonce = _nonces[owner];
-     104                 :          0 :         current = nonce.current();
-     105                 :          0 :         nonce.increment();
-     106                 :            :     }
-     107                 :            : 
-     108                 :            :     /**
-     109                 :            :      * @dev This empty reserved space is put in place to allow future versions to add new
-     110                 :            :      * variables without shifting down storage in the inheritance chain.
-     111                 :            :      * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
-     112                 :            :      */
-     113                 :            :     uint256[49] private __gap;
-     114                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/GatewayMessageHandler.sol.func-sort-c.html b/coverage/libraries/gateway/GatewayMessageHandler.sol.func-sort-c.html deleted file mode 100644 index af32730962..0000000000 --- a/coverage/libraries/gateway/GatewayMessageHandler.sol.func-sort-c.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway/GatewayMessageHandler.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gateway - GatewayMessageHandler.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:060.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
GatewayMessageHandler.encodeFromL2GatewayMsg0
GatewayMessageHandler.encodeFromRouterToGateway0
GatewayMessageHandler.encodeToL2GatewayMsg0
GatewayMessageHandler.parseFromL1GatewayMsg0
GatewayMessageHandler.parseFromRouterToGateway0
GatewayMessageHandler.parseToL1GatewayMsg0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/GatewayMessageHandler.sol.func.html b/coverage/libraries/gateway/GatewayMessageHandler.sol.func.html deleted file mode 100644 index 607dfaad28..0000000000 --- a/coverage/libraries/gateway/GatewayMessageHandler.sol.func.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway/GatewayMessageHandler.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gateway - GatewayMessageHandler.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:060.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
GatewayMessageHandler.encodeFromL2GatewayMsg0
GatewayMessageHandler.encodeFromRouterToGateway0
GatewayMessageHandler.encodeToL2GatewayMsg0
GatewayMessageHandler.parseFromL1GatewayMsg0
GatewayMessageHandler.parseFromRouterToGateway0
GatewayMessageHandler.parseToL1GatewayMsg0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/GatewayMessageHandler.sol.gcov.html b/coverage/libraries/gateway/GatewayMessageHandler.sol.gcov.html deleted file mode 100644 index 5170d6e07c..0000000000 --- a/coverage/libraries/gateway/GatewayMessageHandler.sol.gcov.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway/GatewayMessageHandler.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gateway - GatewayMessageHandler.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:060.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : /// @notice this library manages encoding and decoding of gateway communication
-      22                 :            : library GatewayMessageHandler {
-      23                 :            :     // these are for communication from L1 to L2 gateway
-      24                 :            : 
-      25                 :            :     function encodeToL2GatewayMsg(bytes memory gatewayData, bytes memory callHookData)
-      26                 :            :         internal
-      27                 :            :         pure
-      28                 :            :         returns (bytes memory res)
-      29                 :            :     {
-      30                 :          0 :         res = abi.encode(gatewayData, callHookData);
-      31                 :            :     }
-      32                 :            : 
-      33                 :            :     function parseFromL1GatewayMsg(bytes calldata _data)
-      34                 :            :         internal
-      35                 :            :         pure
-      36                 :            :         returns (bytes memory gatewayData, bytes memory callHookData)
-      37                 :            :     {
-      38                 :            :         // abi decode may revert, but the encoding is done by L1 gateway, so we trust it
-      39                 :          0 :         (gatewayData, callHookData) = abi.decode(_data, (bytes, bytes));
-      40                 :            :     }
-      41                 :            : 
-      42                 :            :     // these are for communication from L2 to L1 gateway
-      43                 :            : 
-      44                 :            :     function encodeFromL2GatewayMsg(uint256 exitNum, bytes memory callHookData)
-      45                 :            :         internal
-      46                 :            :         pure
-      47                 :            :         returns (bytes memory res)
-      48                 :            :     {
-      49                 :          0 :         res = abi.encode(exitNum, callHookData);
-      50                 :            :     }
-      51                 :            : 
-      52                 :            :     function parseToL1GatewayMsg(bytes calldata _data)
-      53                 :            :         internal
-      54                 :            :         pure
-      55                 :            :         returns (uint256 exitNum, bytes memory callHookData)
-      56                 :            :     {
-      57                 :            :         // abi decode may revert, but the encoding is done by L1 gateway, so we trust it
-      58                 :          0 :         (exitNum, callHookData) = abi.decode(_data, (uint256, bytes));
-      59                 :            :     }
-      60                 :            : 
-      61                 :            :     // these are for communication from router to gateway
-      62                 :            : 
-      63                 :            :     function encodeFromRouterToGateway(address _from, bytes calldata _data)
-      64                 :            :         internal
-      65                 :            :         pure
-      66                 :            :         returns (bytes memory res)
-      67                 :            :     {
-      68                 :            :         // abi decode may revert, but the encoding is done by L1 gateway, so we trust it
-      69                 :          0 :         return abi.encode(_from, _data);
-      70                 :            :     }
-      71                 :            : 
-      72                 :            :     function parseFromRouterToGateway(bytes calldata _data)
-      73                 :            :         internal
-      74                 :            :         pure
-      75                 :            :         returns (address, bytes memory res)
-      76                 :            :     {
-      77                 :            :         // abi decode may revert, but the encoding is done by L1 gateway, so we trust it
-      78                 :          0 :         return abi.decode(_data, (address, bytes));
-      79                 :            :     }
-      80                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/GatewayRouter.sol.func-sort-c.html b/coverage/libraries/gateway/GatewayRouter.sol.func-sort-c.html deleted file mode 100644 index 6f8b4138f6..0000000000 --- a/coverage/libraries/gateway/GatewayRouter.sol.func-sort-c.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway/GatewayRouter.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gateway - GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:102245.5 %
Date:2023-04-27 16:26:32Functions:2728.6 %
Branches:61060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
GatewayRouter.calculateL2TokenAddress0
GatewayRouter.finalizeInboundTransfer0
GatewayRouter.getGateway0
GatewayRouter.getOutboundCalldata0
GatewayRouter.outboundTransfer0
GatewayRouter.postUpgradeInit1
GatewayRouter._initialize4
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/GatewayRouter.sol.func.html b/coverage/libraries/gateway/GatewayRouter.sol.func.html deleted file mode 100644 index fc9fff1050..0000000000 --- a/coverage/libraries/gateway/GatewayRouter.sol.func.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway/GatewayRouter.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gateway - GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:102245.5 %
Date:2023-04-27 16:26:32Functions:2728.6 %
Branches:61060.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
GatewayRouter._initialize4
GatewayRouter.calculateL2TokenAddress0
GatewayRouter.finalizeInboundTransfer0
GatewayRouter.getGateway0
GatewayRouter.getOutboundCalldata0
GatewayRouter.outboundTransfer0
GatewayRouter.postUpgradeInit1
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/GatewayRouter.sol.gcov.html b/coverage/libraries/gateway/GatewayRouter.sol.gcov.html deleted file mode 100644 index 95b0a4082f..0000000000 --- a/coverage/libraries/gateway/GatewayRouter.sol.gcov.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway/GatewayRouter.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gateway - GatewayRouter.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:102245.5 %
Date:2023-04-27 16:26:32Functions:2728.6 %
Branches:61060.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../ProxyUtil.sol";
-      22                 :            : import "@openzeppelin/contracts/utils/Address.sol";
-      23                 :            : import "./TokenGateway.sol";
-      24                 :            : import "./GatewayMessageHandler.sol";
-      25                 :            : import "./IGatewayRouter.sol";
-      26                 :            : 
-      27                 :            : /**
-      28                 :            :  * @title Common interface for L1 and L2 Gateway Routers
-      29                 :            :  */
-      30                 :            : abstract contract GatewayRouter is TokenGateway, IGatewayRouter {
-      31                 :            :     using Address for address;
-      32                 :            : 
-      33                 :            :     address internal constant ZERO_ADDR = address(0);
-      34                 :            :     address internal constant DISABLED = address(1);
-      35                 :            : 
-      36                 :            :     mapping(address => address) public l1TokenToGateway;
-      37                 :            :     address public override defaultGateway;
-      38                 :            : 
-      39                 :            :     function postUpgradeInit() external {
-      40                 :            :         // it is assumed the L2 Arbitrum Gateway contract is behind a Proxy controlled by a proxy admin
-      41                 :            :         // this function can only be called by the proxy admin contract
-      42                 :          1 :         address proxyAdmin = ProxyUtil.getProxyAdmin();
-      43         [ +  # ]:          1 :         require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");
-      44                 :            :         // this has no other logic since the current upgrade doesn't require this logic
-      45                 :            :     }
-      46                 :            : 
-      47                 :            :     function _initialize(
-      48                 :            :         address _counterpartGateway,
-      49                 :            :         address _router,
-      50                 :            :         address _defaultGateway
-      51                 :            :     ) internal {
-      52                 :            :         // if you are a router, you can't have a router
-      53         [ #  + ]:          4 :         require(_router == address(0), "BAD_ROUTER");
-      54                 :          4 :         TokenGateway._initialize(_counterpartGateway, _router);
-      55                 :            :         // default gateway can have 0 address
-      56                 :          2 :         defaultGateway = _defaultGateway;
-      57                 :            :     }
-      58                 :            : 
-      59                 :            :     function finalizeInboundTransfer(
-      60                 :            :         address, /* _token */
-      61                 :            :         address, /* _from */
-      62                 :            :         address, /* _to */
-      63                 :            :         uint256, /* _amount */
-      64                 :            :         bytes calldata /* _data */
-      65                 :            :     ) external payable virtual override {
-      66                 :          0 :         revert("ONLY_OUTBOUND_ROUTER");
-      67                 :            :     }
-      68                 :            : 
-      69                 :            :     function outboundTransfer(
-      70                 :            :         address _token,
-      71                 :            :         address _to,
-      72                 :            :         uint256 _amount,
-      73                 :            :         uint256 _maxGas,
-      74                 :            :         uint256 _gasPriceBid,
-      75                 :            :         bytes calldata _data
-      76                 :            :     ) public payable virtual override returns (bytes memory) {
-      77                 :            :         // this function is kept instead of delegating to outboundTransferCustomRefund to allow
-      78                 :            :         // compatibility with older gateways that did not implement outboundTransferCustomRefund
-      79                 :          0 :         address gateway = getGateway(_token);
-      80                 :          0 :         bytes memory gatewayData = GatewayMessageHandler.encodeFromRouterToGateway(
-      81                 :            :             msg.sender,
-      82                 :            :             _data
-      83                 :            :         );
-      84                 :            : 
-      85                 :          0 :         emit TransferRouted(_token, msg.sender, _to, gateway);
-      86                 :          0 :         return
-      87                 :            :             ITokenGateway(gateway).outboundTransfer{ value: msg.value }(
-      88                 :            :                 _token,
-      89                 :            :                 _to,
-      90                 :            :                 _amount,
-      91                 :            :                 _maxGas,
-      92                 :            :                 _gasPriceBid,
-      93                 :            :                 gatewayData
-      94                 :            :             );
-      95                 :            :     }
-      96                 :            : 
-      97                 :            :     function getOutboundCalldata(
-      98                 :            :         address _token,
-      99                 :            :         address _from,
-     100                 :            :         address _to,
-     101                 :            :         uint256 _amount,
-     102                 :            :         bytes memory _data
-     103                 :            :     ) public view virtual override returns (bytes memory) {
-     104                 :          0 :         address gateway = getGateway(_token);
-     105                 :          0 :         return TokenGateway(gateway).getOutboundCalldata(_token, _from, _to, _amount, _data);
-     106                 :            :     }
-     107                 :            : 
-     108                 :            :     function getGateway(address _token) public view virtual override returns (address gateway) {
-     109                 :          6 :         gateway = l1TokenToGateway[_token];
-     110                 :            : 
-     111         [ +  + ]:          6 :         if (gateway == ZERO_ADDR) {
-     112                 :            :             // if no gateway value set, use default gateway
-     113                 :          5 :             gateway = defaultGateway;
-     114                 :            :         }
-     115                 :            : 
-     116         [ +  + ]:          6 :         if (gateway == DISABLED || !gateway.isContract()) {
-     117                 :            :             // not a valid gateway
-     118                 :          5 :             return ZERO_ADDR;
-     119                 :            :         }
-     120                 :            : 
-     121                 :          0 :         return gateway;
-     122                 :            :     }
-     123                 :            : 
-     124                 :            :     function calculateL2TokenAddress(address l1ERC20)
-     125                 :            :         public
-     126                 :            :         view
-     127                 :            :         virtual
-     128                 :            :         override(TokenGateway, ITokenGateway)
-     129                 :            :         returns (address)
-     130                 :            :     {
-     131                 :          0 :         address gateway = getGateway(l1ERC20);
-     132         [ #  # ]:          0 :         if (gateway == ZERO_ADDR) {
-     133                 :          0 :             return ZERO_ADDR;
-     134                 :            :         }
-     135                 :          0 :         return TokenGateway(gateway).calculateL2TokenAddress(l1ERC20);
-     136                 :            :     }
-     137                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/TokenGateway.sol.func-sort-c.html b/coverage/libraries/gateway/TokenGateway.sol.func-sort-c.html deleted file mode 100644 index fba9552d4e..0000000000 --- a/coverage/libraries/gateway/TokenGateway.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway/TokenGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gateway - TokenGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2023-04-27 16:26:32Functions:22100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TokenGateway._initialize17
TokenGateway.isRouter22
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/TokenGateway.sol.func.html b/coverage/libraries/gateway/TokenGateway.sol.func.html deleted file mode 100644 index 815c17f53b..0000000000 --- a/coverage/libraries/gateway/TokenGateway.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway/TokenGateway.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gateway - TokenGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2023-04-27 16:26:32Functions:22100.0 %
Branches:44100.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TokenGateway._initialize17
TokenGateway.isRouter22
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/TokenGateway.sol.gcov.html b/coverage/libraries/gateway/TokenGateway.sol.gcov.html deleted file mode 100644 index af146ceb04..0000000000 --- a/coverage/libraries/gateway/TokenGateway.sol.gcov.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway/TokenGateway.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gateway - TokenGateway.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:55100.0 %
Date:2023-04-27 16:26:32Functions:22100.0 %
Branches:44100.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./ITokenGateway.sol";
-      22                 :            : import "@openzeppelin/contracts/utils/Address.sol";
-      23                 :            : 
-      24                 :            : abstract contract TokenGateway is ITokenGateway {
-      25                 :            :     using Address for address;
-      26                 :            : 
-      27                 :            :     address public counterpartGateway;
-      28                 :            :     address public router;
-      29                 :            : 
-      30                 :            :     // This modifier is overriden in gateways to validate the message sender
-      31                 :            :     // For L1 to L2 messages need to be validated against the aliased counterpartGateway
-      32                 :            :     // For L2 to L1 messages need to be validated against the bridge and L2ToL1Sender
-      33                 :            :     // prettier-ignore
-      34                 :            :     modifier onlyCounterpartGateway() virtual;
-      35                 :            : 
-      36                 :            :     function _initialize(address _counterpartGateway, address _router) internal virtual {
-      37                 :            :         // This initializes internal variables of the abstract contract it can be chained together with other functions.
-      38                 :            :         // It is virtual so subclasses can override or wrap around this logic.
-      39                 :            :         // An example where this is useful is different subclasses that validate the router address differently
-      40         [ +  + ]:         17 :         require(_counterpartGateway != address(0), "INVALID_COUNTERPART");
-      41         [ +  + ]:         16 :         require(counterpartGateway == address(0), "ALREADY_INIT");
-      42                 :         15 :         counterpartGateway = _counterpartGateway;
-      43                 :         15 :         router = _router;
-      44                 :            :     }
-      45                 :            : 
-      46                 :            :     function isRouter(address _target) internal view returns (bool isTargetRouter) {
-      47                 :         22 :         return _target == router;
-      48                 :            :     }
-      49                 :            : 
-      50                 :            :     /**
-      51                 :            :      * @notice Calculate the address used when bridging an ERC20 token
-      52                 :            :      * @dev the L1 and L2 address oracles may not always be in sync.
-      53                 :            :      * For example, a custom token may have been registered but not deploy or the contract self destructed.
-      54                 :            :      * @param l1ERC20 address of L1 token
-      55                 :            :      * @return L2 address of a bridged ERC20 token
-      56                 :            :      */
-      57                 :            :     function calculateL2TokenAddress(address l1ERC20)
-      58                 :            :         public
-      59                 :            :         view
-      60                 :            :         virtual
-      61                 :            :         override
-      62                 :            :         returns (address);
-      63                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/index-sort-b.html b/coverage/libraries/gateway/index-sort-b.html deleted file mode 100644 index 90ff9d03f8..0000000000 --- a/coverage/libraries/gateway/index-sort-b.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gatewayHitTotalCoverage
Test:lcov.infoLines:153345.5 %
Date:2023-04-27 16:26:32Functions:41526.7 %
Branches:101471.4 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
GatewayRouter.sol -
45.5%45.5%
-
45.5 %10 / 2228.6 %2 / 760.0 %6 / 10
GatewayMessageHandler.sol -
0.0%
-
0.0 %0 / 60.0 %0 / 6-0 / 0
TokenGateway.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/index-sort-f.html b/coverage/libraries/gateway/index-sort-f.html deleted file mode 100644 index 47ad0978d8..0000000000 --- a/coverage/libraries/gateway/index-sort-f.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gatewayHitTotalCoverage
Test:lcov.infoLines:153345.5 %
Date:2023-04-27 16:26:32Functions:41526.7 %
Branches:101471.4 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
GatewayMessageHandler.sol -
0.0%
-
0.0 %0 / 60.0 %0 / 6-0 / 0
GatewayRouter.sol -
45.5%45.5%
-
45.5 %10 / 2228.6 %2 / 760.0 %6 / 10
TokenGateway.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/index-sort-l.html b/coverage/libraries/gateway/index-sort-l.html deleted file mode 100644 index 9fd98ab3a6..0000000000 --- a/coverage/libraries/gateway/index-sort-l.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gatewayHitTotalCoverage
Test:lcov.infoLines:153345.5 %
Date:2023-04-27 16:26:32Functions:41526.7 %
Branches:101471.4 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
GatewayMessageHandler.sol -
0.0%
-
0.0 %0 / 60.0 %0 / 6-0 / 0
GatewayRouter.sol -
45.5%45.5%
-
45.5 %10 / 2228.6 %2 / 760.0 %6 / 10
TokenGateway.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/gateway/index.html b/coverage/libraries/gateway/index.html deleted file mode 100644 index 524b0fbd10..0000000000 --- a/coverage/libraries/gateway/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries/gateway - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - libraries/gatewayHitTotalCoverage
Test:lcov.infoLines:153345.5 %
Date:2023-04-27 16:26:32Functions:41526.7 %
Branches:101471.4 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
GatewayMessageHandler.sol -
0.0%
-
0.0 %0 / 60.0 %0 / 6-0 / 0
GatewayRouter.sol -
45.5%45.5%
-
45.5 %10 / 2228.6 %2 / 760.0 %6 / 10
TokenGateway.sol -
100.0%
-
100.0 %5 / 5100.0 %2 / 2100.0 %4 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/index-sort-b.html b/coverage/libraries/index-sort-b.html deleted file mode 100644 index c4353c6972..0000000000 --- a/coverage/libraries/index-sort-b.html +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - librariesHitTotalCoverage
Test:lcov.infoLines:3917022.9 %
Date:2023-04-27 16:26:32Functions:146222.6 %
Branches:106415.6 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
Cloneable.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 20.0 %0 / 2
TransferAndCallToken.sol -
0.0%
-
0.0 %0 / 100.0 %0 / 30.0 %0 / 2
L2GatewayToken.sol -
0.0%
-
0.0 %0 / 70.0 %0 / 30.0 %0 / 4
Whitelist.sol -
0.0%
-
0.0 %0 / 110.0 %0 / 40.0 %0 / 4
ClonableBeaconProxy.sol -
0.0%
-
0.0 %0 / 100.0 %0 / 40.0 %0 / 4
aeWETH.sol -
0.0%
-
0.0 %0 / 110.0 %0 / 70.0 %0 / 4
draft-ERC20PermitUpgradeable.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 60.0 %0 / 4
BytesLib.sol -
0.0%
-
0.0 %0 / 160.0 %0 / 40.0 %0 / 8
BytesParser.sol -
0.0%
-
0.0 %0 / 210.0 %0 / 20.0 %0 / 10
ERC20Upgradeable.sol -
63.3%63.3%
-
63.3 %38 / 6061.9 %13 / 2145.5 %10 / 22
L2CustomGatewayToken.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
ERC165.sol -
100.0%
-
100.0 %1 / 1100.0 %1 / 1-0 / 0
ProxyUtil.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 1-0 / 0
AddressAliasHelper.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
aeERC20.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/index-sort-f.html b/coverage/libraries/index-sort-f.html deleted file mode 100644 index 71c882d694..0000000000 --- a/coverage/libraries/index-sort-f.html +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - librariesHitTotalCoverage
Test:lcov.infoLines:3917022.9 %
Date:2023-04-27 16:26:32Functions:146222.6 %
Branches:106415.6 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2CustomGatewayToken.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
ProxyUtil.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 1-0 / 0
aeERC20.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 1-0 / 0
BytesParser.sol -
0.0%
-
0.0 %0 / 210.0 %0 / 20.0 %0 / 10
Cloneable.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 20.0 %0 / 2
AddressAliasHelper.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
L2GatewayToken.sol -
0.0%
-
0.0 %0 / 70.0 %0 / 30.0 %0 / 4
TransferAndCallToken.sol -
0.0%
-
0.0 %0 / 100.0 %0 / 30.0 %0 / 2
BytesLib.sol -
0.0%
-
0.0 %0 / 160.0 %0 / 40.0 %0 / 8
Whitelist.sol -
0.0%
-
0.0 %0 / 110.0 %0 / 40.0 %0 / 4
ClonableBeaconProxy.sol -
0.0%
-
0.0 %0 / 100.0 %0 / 40.0 %0 / 4
draft-ERC20PermitUpgradeable.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 60.0 %0 / 4
aeWETH.sol -
0.0%
-
0.0 %0 / 110.0 %0 / 70.0 %0 / 4
ERC20Upgradeable.sol -
63.3%63.3%
-
63.3 %38 / 6061.9 %13 / 2145.5 %10 / 22
ERC165.sol -
100.0%
-
100.0 %1 / 1100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/index-sort-l.html b/coverage/libraries/index-sort-l.html deleted file mode 100644 index 3bc996c03a..0000000000 --- a/coverage/libraries/index-sort-l.html +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - librariesHitTotalCoverage
Test:lcov.infoLines:3917022.9 %
Date:2023-04-27 16:26:32Functions:146222.6 %
Branches:106415.6 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
L2CustomGatewayToken.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
ProxyUtil.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 1-0 / 0
AddressAliasHelper.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
Cloneable.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 20.0 %0 / 2
aeERC20.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 1-0 / 0
L2GatewayToken.sol -
0.0%
-
0.0 %0 / 70.0 %0 / 30.0 %0 / 4
TransferAndCallToken.sol -
0.0%
-
0.0 %0 / 100.0 %0 / 30.0 %0 / 2
ClonableBeaconProxy.sol -
0.0%
-
0.0 %0 / 100.0 %0 / 40.0 %0 / 4
Whitelist.sol -
0.0%
-
0.0 %0 / 110.0 %0 / 40.0 %0 / 4
aeWETH.sol -
0.0%
-
0.0 %0 / 110.0 %0 / 70.0 %0 / 4
draft-ERC20PermitUpgradeable.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 60.0 %0 / 4
BytesLib.sol -
0.0%
-
0.0 %0 / 160.0 %0 / 40.0 %0 / 8
BytesParser.sol -
0.0%
-
0.0 %0 / 210.0 %0 / 20.0 %0 / 10
ERC20Upgradeable.sol -
63.3%63.3%
-
63.3 %38 / 6061.9 %13 / 2145.5 %10 / 22
ERC165.sol -
100.0%
-
100.0 %1 / 1100.0 %1 / 1-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/libraries/index.html b/coverage/libraries/index.html deleted file mode 100644 index 020bffaaab..0000000000 --- a/coverage/libraries/index.html +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - - LCOV - lcov.info - libraries - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - librariesHitTotalCoverage
Test:lcov.infoLines:3917022.9 %
Date:2023-04-27 16:26:32Functions:146222.6 %
Branches:106415.6 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
AddressAliasHelper.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
BytesLib.sol -
0.0%
-
0.0 %0 / 160.0 %0 / 40.0 %0 / 8
BytesParser.sol -
0.0%
-
0.0 %0 / 210.0 %0 / 20.0 %0 / 10
ClonableBeaconProxy.sol -
0.0%
-
0.0 %0 / 100.0 %0 / 40.0 %0 / 4
Cloneable.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 20.0 %0 / 2
ERC165.sol -
100.0%
-
100.0 %1 / 1100.0 %1 / 1-0 / 0
ERC20Upgradeable.sol -
63.3%63.3%
-
63.3 %38 / 6061.9 %13 / 2145.5 %10 / 22
L2CustomGatewayToken.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
L2GatewayToken.sol -
0.0%
-
0.0 %0 / 70.0 %0 / 30.0 %0 / 4
ProxyUtil.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 1-0 / 0
TransferAndCallToken.sol -
0.0%
-
0.0 %0 / 100.0 %0 / 30.0 %0 / 2
Whitelist.sol -
0.0%
-
0.0 %0 / 110.0 %0 / 40.0 %0 / 4
aeERC20.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 1-0 / 0
aeWETH.sol -
0.0%
-
0.0 %0 / 110.0 %0 / 70.0 %0 / 4
draft-ERC20PermitUpgradeable.sol -
0.0%
-
0.0 %0 / 120.0 %0 / 60.0 %0 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/ruby.png b/coverage/ruby.png deleted file mode 100644 index 991b6d4ec9e78be165e3ef757eed1aada287364d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^FceV#7`HfI^%F z9+AZi4BSE>%y{W;-5;PJOS+@4BLl<6e(pbstUx|nfKQ0)e^Y%R^MdiLxj>4`)5S5Q b;#P73kj=!v_*DHKNFRfztDnm{r-UW|iOwIS diff --git a/coverage/snow.png b/coverage/snow.png deleted file mode 100644 index 2cdae107fceec6e7f02ac7acb4a34a82a540caa5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga>?NMQuI!iC1^MM!lvI6;R0X`wF|Ns97GD8ntt^-nBo-U3d c6}OTTfNUlP#;5A{K>8RwUHx3vIVCg!071?oo&W#< diff --git a/coverage/test/AddressMappingTest.sol.func-sort-c.html b/coverage/test/AddressMappingTest.sol.func-sort-c.html deleted file mode 100644 index 4214503e36..0000000000 --- a/coverage/test/AddressMappingTest.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/AddressMappingTest.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - AddressMappingTest.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
AddressMappingTest.getL1AddressTest0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/AddressMappingTest.sol.func.html b/coverage/test/AddressMappingTest.sol.func.html deleted file mode 100644 index 89167466cb..0000000000 --- a/coverage/test/AddressMappingTest.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/AddressMappingTest.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - AddressMappingTest.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
AddressMappingTest.getL1AddressTest0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/AddressMappingTest.sol.gcov.html b/coverage/test/AddressMappingTest.sol.gcov.html deleted file mode 100644 index d8877e7636..0000000000 --- a/coverage/test/AddressMappingTest.sol.gcov.html +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - LCOV - lcov.info - test/AddressMappingTest.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - AddressMappingTest.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:010.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../arbitrum/L2ArbitrumMessenger.sol";
-      22                 :            : import "../libraries/AddressAliasHelper.sol";
-      23                 :            : 
-      24                 :            : contract AddressMappingTest is L2ArbitrumMessenger {
-      25                 :            :     function getL1AddressTest(address sender) external pure returns (address l1Address) {
-      26                 :          0 :         return AddressAliasHelper.undoL1ToL2Alias(sender);
-      27                 :            :     }
-      28                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/ArbSysMock.sol.func-sort-c.html b/coverage/test/ArbSysMock.sol.func-sort-c.html deleted file mode 100644 index 64784621e3..0000000000 --- a/coverage/test/ArbSysMock.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/ArbSysMock.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - ArbSysMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ArbSysMock.sendTxToL10
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/ArbSysMock.sol.func.html b/coverage/test/ArbSysMock.sol.func.html deleted file mode 100644 index 3652783755..0000000000 --- a/coverage/test/ArbSysMock.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/ArbSysMock.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - ArbSysMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ArbSysMock.sendTxToL10
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/ArbSysMock.sol.gcov.html b/coverage/test/ArbSysMock.sol.gcov.html deleted file mode 100644 index 30477be16d..0000000000 --- a/coverage/test/ArbSysMock.sol.gcov.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - LCOV - lcov.info - test/ArbSysMock.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - ArbSysMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : pragma solidity ^0.8.0;
-       2                 :            : 
-       3                 :            : contract ArbSysMock {
-       4                 :            :     event ArbSysL2ToL1Tx(address from, address to, uint256 value, bytes data);
-       5                 :            :     uint256 counter;
-       6                 :            : 
-       7                 :            :     function sendTxToL1(address destination, bytes calldata calldataForL1)
-       8                 :            :         external
-       9                 :            :         payable
-      10                 :            :         returns (uint256 exitNum)
-      11                 :            :     {
-      12                 :          0 :         exitNum = counter;
-      13                 :          0 :         counter = exitNum + 1;
-      14                 :          0 :         emit ArbSysL2ToL1Tx(msg.sender, destination, msg.value, calldataForL1);
-      15                 :          0 :         return exitNum;
-      16                 :            :     }
-      17                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/InboxMock.sol.func-sort-c.html b/coverage/test/InboxMock.sol.func-sort-c.html deleted file mode 100644 index ab174d644f..0000000000 --- a/coverage/test/InboxMock.sol.func-sort-c.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test/InboxMock.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - InboxMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:141687.5 %
Date:2023-04-27 16:26:32Functions:66100.0 %
Branches:2450.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
ERC20InboxMock.createRetryableTicket2
AbsInboxMock.activeOutbox4
AbsInboxMock.l2ToL1Sender4
AbsInboxMock.setL2ToL1Sender4
AbsInboxMock.bridge14
InboxMock.createRetryableTicket15
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/InboxMock.sol.func.html b/coverage/test/InboxMock.sol.func.html deleted file mode 100644 index ed8d207424..0000000000 --- a/coverage/test/InboxMock.sol.func.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test/InboxMock.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - InboxMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:141687.5 %
Date:2023-04-27 16:26:32Functions:66100.0 %
Branches:2450.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
AbsInboxMock.activeOutbox4
AbsInboxMock.bridge14
AbsInboxMock.l2ToL1Sender4
AbsInboxMock.setL2ToL1Sender4
ERC20InboxMock.createRetryableTicket2
InboxMock.createRetryableTicket15
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/InboxMock.sol.gcov.html b/coverage/test/InboxMock.sol.gcov.html deleted file mode 100644 index 865902d45c..0000000000 --- a/coverage/test/InboxMock.sol.gcov.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - LCOV - lcov.info - test/InboxMock.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - InboxMock.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:141687.5 %
Date:2023-04-27 16:26:32Functions:66100.0 %
Branches:2450.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol";
-      22                 :            : import "@arbitrum/nitro-contracts/src/bridge/IBridge.sol";
-      23                 :            : 
-      24                 :            : abstract contract AbsInboxMock {
-      25                 :            :     address l2ToL1SenderMock = address(0);
-      26                 :            : 
-      27                 :            :     event TicketData(uint256 maxSubmissionCost);
-      28                 :            :     event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress);
-      29                 :            :     event InboxRetryableTicket(address from, address to, uint256 value, uint256 maxGas, bytes data);
-      30                 :            : 
-      31                 :            :     function bridge() external view returns (IBridge) {
-      32                 :         14 :         return IBridge(address(this));
-      33                 :            :     }
-      34                 :            : 
-      35                 :            :     function activeOutbox() external view returns (address) {
-      36                 :          4 :         return address(this);
-      37                 :            :     }
-      38                 :            : 
-      39                 :            :     function setL2ToL1Sender(address sender) external {
-      40                 :          4 :         l2ToL1SenderMock = sender;
-      41                 :            :     }
-      42                 :            : 
-      43                 :            :     function l2ToL1Sender() external view returns (address) {
-      44                 :          4 :         return l2ToL1SenderMock;
-      45                 :            :     }
-      46                 :            : }
-      47                 :            : 
-      48                 :            : contract InboxMock is AbsInboxMock {
-      49                 :            :     function createRetryableTicket(
-      50                 :            :         address to,
-      51                 :            :         uint256 l2CallValue,
-      52                 :            :         uint256 maxSubmissionCost,
-      53                 :            :         address excessFeeRefundAddress,
-      54                 :            :         address callValueRefundAddress,
-      55                 :            :         uint256 gasLimit,
-      56                 :            :         uint256 maxFeePerGas,
-      57                 :            :         bytes calldata data
-      58                 :            :     ) external payable returns (uint256) {
-      59         [ #  + ]:         15 :         if (msg.value < (maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas)) {
-      60                 :          0 :             revert("WRONG_ETH_VALUE");
-      61                 :            :         }
-      62                 :         15 :         emit TicketData(maxSubmissionCost);
-      63                 :         15 :         emit RefundAddresses(excessFeeRefundAddress, callValueRefundAddress);
-      64                 :         15 :         emit InboxRetryableTicket(msg.sender, to, l2CallValue, gasLimit, data);
-      65                 :         15 :         return 0;
-      66                 :            :     }
-      67                 :            : }
-      68                 :            : 
-      69                 :            : contract ERC20InboxMock is AbsInboxMock {
-      70                 :            :     event ERC20InboxRetryableTicket(
-      71                 :            :         address from,
-      72                 :            :         address to,
-      73                 :            :         uint256 l2CallValue,
-      74                 :            :         uint256 maxGas,
-      75                 :            :         uint256 gasPrice,
-      76                 :            :         uint256 tokenTotalFeeAmount,
-      77                 :            :         bytes data
-      78                 :            :     );
-      79                 :            : 
-      80                 :            :     function createRetryableTicket(
-      81                 :            :         address to,
-      82                 :            :         uint256 l2CallValue,
-      83                 :            :         uint256 maxSubmissionCost,
-      84                 :            :         address excessFeeRefundAddress,
-      85                 :            :         address callValueRefundAddress,
-      86                 :            :         uint256 gasLimit,
-      87                 :            :         uint256 maxFeePerGas,
-      88                 :            :         uint256 tokenTotalFeeAmount,
-      89                 :            :         bytes calldata data
-      90                 :            :     ) external returns (uint256) {
-      91                 :            :         // ensure the user's deposit alone will make submission succeed
-      92         [ #  + ]:          2 :         if (tokenTotalFeeAmount < (maxSubmissionCost + l2CallValue + gasLimit * maxFeePerGas)) {
-      93                 :          0 :             revert("WRONG_TOKEN_VALUE");
-      94                 :            :         }
-      95                 :            : 
-      96                 :          2 :         emit TicketData(maxSubmissionCost);
-      97                 :          2 :         emit RefundAddresses(excessFeeRefundAddress, callValueRefundAddress);
-      98                 :          2 :         emit ERC20InboxRetryableTicket(
-      99                 :            :             msg.sender,
-     100                 :            :             to,
-     101                 :            :             l2CallValue,
-     102                 :            :             gasLimit,
-     103                 :            :             maxFeePerGas,
-     104                 :            :             tokenTotalFeeAmount,
-     105                 :            :             data
-     106                 :            :         );
-     107                 :          2 :         return 0;
-     108                 :            :     }
-     109                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestArbCustomToken.sol.func-sort-c.html b/coverage/test/TestArbCustomToken.sol.func-sort-c.html deleted file mode 100644 index f4043751fe..0000000000 --- a/coverage/test/TestArbCustomToken.sol.func-sort-c.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestArbCustomToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestArbCustomToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
MintableTestArbCustomToken.userMint0
ReverseTestArbCustomToken.mint0
ReverseTestArbCustomToken.someWackyCustomStuff0
TestArbCustomToken.bridgeBurn0
TestArbCustomToken.bridgeMint0
TestArbCustomToken.someWackyCustomStuff0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestArbCustomToken.sol.func.html b/coverage/test/TestArbCustomToken.sol.func.html deleted file mode 100644 index e346ea2b88..0000000000 --- a/coverage/test/TestArbCustomToken.sol.func.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestArbCustomToken.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestArbCustomToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
MintableTestArbCustomToken.userMint0
ReverseTestArbCustomToken.mint0
ReverseTestArbCustomToken.someWackyCustomStuff0
TestArbCustomToken.bridgeBurn0
TestArbCustomToken.bridgeMint0
TestArbCustomToken.someWackyCustomStuff0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestArbCustomToken.sol.gcov.html b/coverage/test/TestArbCustomToken.sol.gcov.html deleted file mode 100644 index 306e54285f..0000000000 --- a/coverage/test/TestArbCustomToken.sol.gcov.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestArbCustomToken.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestArbCustomToken.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:040.0 %
Date:2023-04-27 16:26:32Functions:060.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../arbitrum/IArbToken.sol";
-      22                 :            : import "../arbitrum/ReverseArbToken.sol";
-      23                 :            : import "../libraries/aeERC20.sol";
-      24                 :            : 
-      25                 :            : contract TestArbCustomToken is aeERC20, IArbToken {
-      26                 :            :     address public l2Gateway;
-      27                 :            :     address public override l1Address;
-      28                 :            : 
-      29                 :            :     modifier onlyGateway() {
-      30                 :            :         require(msg.sender == l2Gateway, "ONLY_l2GATEWAY");
-      31                 :            :         _;
-      32                 :            :     }
-      33                 :            : 
-      34                 :            :     constructor(address _l2Gateway, address _l1Address) {
-      35                 :            :         l2Gateway = _l2Gateway;
-      36                 :            :         l1Address = _l1Address;
-      37                 :            :         aeERC20._initialize("TestCustomToken", "CARB", uint8(18));
-      38                 :            :     }
-      39                 :            : 
-      40                 :            :     function someWackyCustomStuff() public {}
-      41                 :            : 
-      42                 :            :     function bridgeMint(address account, uint256 amount) external virtual override onlyGateway {
-      43                 :          0 :         _mint(account, amount);
-      44                 :            :     }
-      45                 :            : 
-      46                 :            :     function bridgeBurn(address account, uint256 amount) external virtual override onlyGateway {
-      47                 :          0 :         _burn(account, amount);
-      48                 :            :     }
-      49                 :            : }
-      50                 :            : 
-      51                 :            : contract MintableTestArbCustomToken is TestArbCustomToken {
-      52                 :            :     constructor(address _l2Gateway, address _l1Address) TestArbCustomToken(_l2Gateway, _l1Address){}
-      53                 :            : 
-      54                 :            :     function userMint(address account, uint256 amount) external {
-      55                 :          0 :         _mint(account, amount);
-      56                 :            :     }
-      57                 :            : }
-      58                 :            : 
-      59                 :            : contract ReverseTestArbCustomToken is aeERC20, IArbToken, ReverseArbToken {
-      60                 :            :     address public l2Gateway;
-      61                 :            :     address public override l1Address;
-      62                 :            : 
-      63                 :            :     modifier onlyGateway() {
-      64                 :            :         require(msg.sender == l2Gateway, "ONLY_l2GATEWAY");
-      65                 :            :         _;
-      66                 :            :     }
-      67                 :            : 
-      68                 :            :     constructor(address _l2Gateway, address _l1Address) {
-      69                 :            :         l2Gateway = _l2Gateway;
-      70                 :            :         l1Address = _l1Address;
-      71                 :            :         aeERC20._initialize("TestReverseCustomToken", "RARB", uint8(18));
-      72                 :            :     }
-      73                 :            : 
-      74                 :            :     function someWackyCustomStuff() public {}
-      75                 :            : 
-      76                 :            :     function mint() external {
-      77                 :          0 :         _mint(msg.sender, 50000000);
-      78                 :            :     }
-      79                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestArbCustomTokenBurnFee.sol.func-sort-c.html b/coverage/test/TestArbCustomTokenBurnFee.sol.func-sort-c.html deleted file mode 100644 index 4135ebf1c4..0000000000 --- a/coverage/test/TestArbCustomTokenBurnFee.sol.func-sort-c.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestArbCustomTokenBurnFee.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestArbCustomTokenBurnFee.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TestArbCustomTokenBurnFee._burn0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestArbCustomTokenBurnFee.sol.func.html b/coverage/test/TestArbCustomTokenBurnFee.sol.func.html deleted file mode 100644 index e6e96637c7..0000000000 --- a/coverage/test/TestArbCustomTokenBurnFee.sol.func.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestArbCustomTokenBurnFee.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestArbCustomTokenBurnFee.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- -
- - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TestArbCustomTokenBurnFee._burn0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestArbCustomTokenBurnFee.sol.gcov.html b/coverage/test/TestArbCustomTokenBurnFee.sol.gcov.html deleted file mode 100644 index 19090fe970..0000000000 --- a/coverage/test/TestArbCustomTokenBurnFee.sol.gcov.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestArbCustomTokenBurnFee.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestArbCustomTokenBurnFee.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:010.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "./TestArbCustomToken.sol";
-      22                 :            : 
-      23                 :            : contract TestArbCustomTokenBurnFee is TestArbCustomToken {
-      24                 :            :     constructor(
-      25                 :            :         address _l2Gateway,
-      26                 :            :         address _l1Address
-      27                 :            :     ) TestArbCustomToken(_l2Gateway, _l1Address) {}
-      28                 :            : 
-      29                 :            :     // this token transfer extra 1 wei from the sender as fee when it burn token
-      30                 :            :     // alternatively, it can also be a callback that pass execution to the user
-      31                 :            :     function _burn(address account, uint256 amount) internal override {
-      32                 :          0 :         super._burn(account, amount);
-      33                 :          0 :         _transfer(account, address(1), 1);
-      34                 :            :     }
-      35                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestBytesParser.sol.func-sort-c.html b/coverage/test/TestBytesParser.sol.func-sort-c.html deleted file mode 100644 index 24ddc1b499..0000000000 --- a/coverage/test/TestBytesParser.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestBytesParser.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestBytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TestBytesParser.bytesToString0
TestBytesParser.bytesToUint80
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestBytesParser.sol.func.html b/coverage/test/TestBytesParser.sol.func.html deleted file mode 100644 index 2203ea8f31..0000000000 --- a/coverage/test/TestBytesParser.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestBytesParser.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestBytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TestBytesParser.bytesToString0
TestBytesParser.bytesToUint80
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestBytesParser.sol.gcov.html b/coverage/test/TestBytesParser.sol.gcov.html deleted file mode 100644 index beffbc48e6..0000000000 --- a/coverage/test/TestBytesParser.sol.gcov.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestBytesParser.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestBytesParser.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:020.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../libraries/BytesParser.sol";
-      22                 :            : 
-      23                 :            : contract TestBytesParser {
-      24                 :            :     function bytesToString(bytes memory input)
-      25                 :            :         public
-      26                 :            :         pure
-      27                 :            :         returns (bool success, string memory res)
-      28                 :            :     {
-      29                 :          0 :         return BytesParser.toString(input);
-      30                 :            :     }
-      31                 :            : 
-      32                 :            :     function bytesToUint8(bytes memory input) public pure returns (bool, uint8) {
-      33                 :          0 :         return BytesParser.toUint8(input);
-      34                 :            :     }
-      35                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestCustomTokenL1.sol.func-sort-c.html b/coverage/test/TestCustomTokenL1.sol.func-sort-c.html deleted file mode 100644 index 6f64c2488e..0000000000 --- a/coverage/test/TestCustomTokenL1.sol.func-sort-c.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestCustomTokenL1.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestCustomTokenL1.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:0110.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
MintableTestCustomTokenL1.balanceOf0
MintableTestCustomTokenL1.bridgeMint0
MintableTestCustomTokenL1.transferFrom0
ReverseTestCustomTokenL1.balanceOf0
ReverseTestCustomTokenL1.bridgeBurn0
ReverseTestCustomTokenL1.transferFrom0
TestCustomTokenL1.balanceOf0
TestCustomTokenL1.isArbitrumEnabled0
TestCustomTokenL1.mint0
TestCustomTokenL1.registerTokenOnL20
TestCustomTokenL1.transferFrom0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestCustomTokenL1.sol.func.html b/coverage/test/TestCustomTokenL1.sol.func.html deleted file mode 100644 index a85935a0a5..0000000000 --- a/coverage/test/TestCustomTokenL1.sol.func.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestCustomTokenL1.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestCustomTokenL1.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:0110.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
MintableTestCustomTokenL1.balanceOf0
MintableTestCustomTokenL1.bridgeMint0
MintableTestCustomTokenL1.transferFrom0
ReverseTestCustomTokenL1.balanceOf0
ReverseTestCustomTokenL1.bridgeBurn0
ReverseTestCustomTokenL1.transferFrom0
TestCustomTokenL1.balanceOf0
TestCustomTokenL1.isArbitrumEnabled0
TestCustomTokenL1.mint0
TestCustomTokenL1.registerTokenOnL20
TestCustomTokenL1.transferFrom0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestCustomTokenL1.sol.gcov.html b/coverage/test/TestCustomTokenL1.sol.gcov.html deleted file mode 100644 index 21d54bd954..0000000000 --- a/coverage/test/TestCustomTokenL1.sol.gcov.html +++ /dev/null @@ -1,253 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestCustomTokenL1.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestCustomTokenL1.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:0160.0 %
Date:2023-04-27 16:26:32Functions:0110.0 %
Branches:020.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.0;
-       4                 :            : 
-       5                 :            : import "../libraries/aeERC20.sol";
-       6                 :            : import "../ethereum/ICustomToken.sol";
-       7                 :            : import "../ethereum/gateway/L1CustomGateway.sol";
-       8                 :            : import "../ethereum/gateway/L1GatewayRouter.sol";
-       9                 :            : import "@openzeppelin/contracts/utils/Context.sol";
-      10                 :            : import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
-      11                 :            : 
-      12                 :            : interface IL1CustomGateway {
-      13                 :            :     function registerTokenToL2(
-      14                 :            :         address _l2Address,
-      15                 :            :         uint256 _maxGas,
-      16                 :            :         uint256 _gasPriceBid,
-      17                 :            :         uint256 _maxSubmissionCost,
-      18                 :            :         address _creditBackAddress
-      19                 :            :     ) external payable returns (uint256);
-      20                 :            : }
-      21                 :            : 
-      22                 :            : interface IGatewayRouter2 {
-      23                 :            :     function setGateway(
-      24                 :            :         address _gateway,
-      25                 :            :         uint256 _maxGas,
-      26                 :            :         uint256 _gasPriceBid,
-      27                 :            :         uint256 _maxSubmissionCost,
-      28                 :            :         address _creditBackAddress
-      29                 :            :     ) external payable returns (uint256);
-      30                 :            : }
-      31                 :            : 
-      32                 :            : contract TestCustomTokenL1 is aeERC20, ICustomToken {
-      33                 :            :     address public gateway;
-      34                 :            :     address public router;
-      35                 :            :     bool private shouldRegisterGateway;
-      36                 :            : 
-      37                 :            :     constructor(address _gateway, address _router) {
-      38                 :            :         gateway = _gateway;
-      39                 :            :         router = _router;
-      40                 :            :         aeERC20._initialize("TestCustomToken", "CARB", uint8(18));
-      41                 :            :     }
-      42                 :            : 
-      43                 :            :     function mint() external {
-      44                 :          0 :         _mint(msg.sender, 50000000);
-      45                 :            :     }
-      46                 :            : 
-      47                 :            :     function transferFrom(
-      48                 :            :         address sender,
-      49                 :            :         address recipient,
-      50                 :            :         uint256 amount
-      51                 :            :     ) public virtual override(IERC20Upgradeable, ERC20Upgradeable, ICustomToken) returns (bool) {
-      52                 :          0 :         return ERC20Upgradeable.transferFrom(sender, recipient, amount);
-      53                 :            :     }
-      54                 :            : 
-      55                 :            :     function balanceOf(address account)
-      56                 :            :         public
-      57                 :            :         view
-      58                 :            :         virtual
-      59                 :            :         override(IERC20Upgradeable, ERC20Upgradeable, ICustomToken)
-      60                 :            :         returns (uint256)
-      61                 :            :     {
-      62                 :          0 :         return ERC20Upgradeable.balanceOf(account);
-      63                 :            :     }
-      64                 :            : 
-      65                 :            :     /// @dev we only set shouldRegisterGateway to true when in `registerTokenOnL2`
-      66                 :            :     function isArbitrumEnabled() external view override returns (uint8) {
-      67         [ #  # ]:          0 :         require(shouldRegisterGateway, "NOT_EXPECTED_CALL");
-      68                 :          0 :         return uint8(0xb1);
-      69                 :            :     }
-      70                 :            : 
-      71                 :            :     function registerTokenOnL2(
-      72                 :            :         address l2CustomTokenAddress,
-      73                 :            :         uint256 maxSubmissionCostForCustomGateway,
-      74                 :            :         uint256 maxSubmissionCostForRouter,
-      75                 :            :         uint256 maxGasForCustomGateway,
-      76                 :            :         uint256 maxGasForRouter,
-      77                 :            :         uint256 gasPriceBid,
-      78                 :            :         uint256 valueForGateway,
-      79                 :            :         uint256 valueForRouter,
-      80                 :            :         address creditBackAddress
-      81                 :            :     ) public payable override {
-      82                 :            :         // we temporarily set `shouldRegisterGateway` to true for the callback in registerTokenToL2 to succeed
-      83                 :          0 :         bool prev = shouldRegisterGateway;
-      84                 :          0 :         shouldRegisterGateway = true;
-      85                 :            : 
-      86                 :          0 :         IL1CustomGateway(gateway).registerTokenToL2{ value: valueForGateway }(
-      87                 :            :             l2CustomTokenAddress,
-      88                 :            :             maxGasForCustomGateway,
-      89                 :            :             gasPriceBid,
-      90                 :            :             maxSubmissionCostForCustomGateway,
-      91                 :            :             creditBackAddress
-      92                 :            :         );
-      93                 :            : 
-      94                 :          0 :         IGatewayRouter2(router).setGateway{ value: valueForRouter }(
-      95                 :            :             gateway,
-      96                 :            :             maxGasForRouter,
-      97                 :            :             gasPriceBid,
-      98                 :            :             maxSubmissionCostForRouter,
-      99                 :            :             creditBackAddress
-     100                 :            :         );
-     101                 :            : 
-     102                 :          0 :         shouldRegisterGateway = prev;
-     103                 :            :     }
-     104                 :            : }
-     105                 :            : 
-     106                 :            : contract MintableTestCustomTokenL1 is L1MintableToken, TestCustomTokenL1 {
-     107                 :            :     constructor(address _gateway, address _router) TestCustomTokenL1(_gateway, _router) {}
-     108                 :            : 
-     109                 :            :     modifier onlyGateway() {
-     110                 :            :         require(msg.sender == gateway, "ONLY_l1GATEWAY");
-     111                 :            :         _;
-     112                 :            :     }
-     113                 :            : 
-     114                 :            :     function bridgeMint(address account, uint256 amount)
-     115                 :            :         public
-     116                 :            :         override(L1MintableToken)
-     117                 :            :         onlyGateway
-     118                 :            :     {
-     119                 :          0 :         _mint(account, amount);
-     120                 :            :     }
-     121                 :            : 
-     122                 :            :     function balanceOf(address account)
-     123                 :            :         public
-     124                 :            :         view
-     125                 :            :         virtual
-     126                 :            :         override(TestCustomTokenL1, ICustomToken)
-     127                 :            :         returns (uint256 amount)
-     128                 :            :     {
-     129                 :          0 :         return super.balanceOf(account);
-     130                 :            :     }
-     131                 :            : 
-     132                 :            :     function transferFrom(
-     133                 :            :         address sender,
-     134                 :            :         address recipient,
-     135                 :            :         uint256 amount
-     136                 :            :     ) public virtual override(TestCustomTokenL1, ICustomToken) returns (bool) {
-     137                 :          0 :         return super.transferFrom(sender, recipient, amount);
-     138                 :            :     }
-     139                 :            : }
-     140                 :            : 
-     141                 :            : contract ReverseTestCustomTokenL1 is L1ReverseToken, MintableTestCustomTokenL1 {
-     142                 :            :     constructor(address _gateway, address _router) MintableTestCustomTokenL1(_gateway, _router) {}
-     143                 :            : 
-     144                 :            :     function bridgeBurn(address account, uint256 amount)
-     145                 :            :         public
-     146                 :            :         override(L1ReverseToken)
-     147                 :            :         onlyGateway
-     148                 :            :     {
-     149                 :          0 :         _burn(account, amount);
-     150                 :            :     }
-     151                 :            : 
-     152                 :            :     function balanceOf(address account)
-     153                 :            :         public
-     154                 :            :         view
-     155                 :            :         override(MintableTestCustomTokenL1, ICustomToken)
-     156                 :            :         returns (uint256 amount)
-     157                 :            :     {
-     158                 :          0 :         return super.balanceOf(account);
-     159                 :            :     }
-     160                 :            : 
-     161                 :            :     function transferFrom(
-     162                 :            :         address sender,
-     163                 :            :         address recipient,
-     164                 :            :         uint256 amount
-     165                 :            :     ) public override(MintableTestCustomTokenL1, ICustomToken) returns (bool) {
-     166                 :          0 :         return super.transferFrom(sender, recipient, amount);
-     167                 :            :     }
-     168                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestERC20.sol.func-sort-c.html b/coverage/test/TestERC20.sol.func-sort-c.html deleted file mode 100644 index c2a02ea51f..0000000000 --- a/coverage/test/TestERC20.sol.func-sort-c.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestERC20.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11010.0 %
Date:2023-04-27 16:26:32Functions:1520.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
Bytes32ERC20.approve0
Bytes32ERC20.mint0
Bytes32ERC20.transfer0
Bytes32ERC20.transferFrom0
TestERC20.mint2
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestERC20.sol.func.html b/coverage/test/TestERC20.sol.func.html deleted file mode 100644 index 9c358efc02..0000000000 --- a/coverage/test/TestERC20.sol.func.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestERC20.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11010.0 %
Date:2023-04-27 16:26:32Functions:1520.0 %
Branches:020.0 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
Bytes32ERC20.approve0
Bytes32ERC20.mint0
Bytes32ERC20.transfer0
Bytes32ERC20.transferFrom0
TestERC20.mint2
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestERC20.sol.gcov.html b/coverage/test/TestERC20.sol.gcov.html deleted file mode 100644 index be999026db..0000000000 --- a/coverage/test/TestERC20.sol.gcov.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestERC20.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestERC20.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:11010.0 %
Date:2023-04-27 16:26:32Functions:1520.0 %
Branches:020.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2020, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../libraries/aeERC20.sol";
-      22                 :            : 
-      23                 :            : contract TestERC20 is aeERC20 {
-      24                 :            :     constructor() {
-      25                 :            :         aeERC20._initialize("IntArbTestToken", "IARB", uint8(18));
-      26                 :            :     }
-      27                 :            : 
-      28                 :            :     function mint() external {
-      29                 :          2 :         _mint(msg.sender, 50000000);
-      30                 :            :     }
-      31                 :            : }
-      32                 :            : 
-      33                 :            : // test token code inspired from maker
-      34                 :            : contract Bytes32ERC20 {
-      35                 :            :     mapping(address => uint256) public balanceOf;
-      36                 :            :     mapping(address => mapping(address => uint256)) public allowance;
-      37                 :            : 
-      38                 :            :     function transfer(address dst, uint256 wad) public returns (bool) {
-      39                 :          0 :         return transferFrom(msg.sender, dst, wad);
-      40                 :            :     }
-      41                 :            : 
-      42                 :            :     function transferFrom(
-      43                 :            :         address src,
-      44                 :            :         address dst,
-      45                 :            :         uint256 wad
-      46                 :            :     ) public returns (bool) {
-      47         [ #  # ]:          0 :         if (src != msg.sender) {
-      48                 :          0 :             allowance[src][msg.sender] = allowance[src][msg.sender] - wad;
-      49                 :            :         }
-      50                 :            : 
-      51                 :          0 :         balanceOf[src] = balanceOf[src] - wad;
-      52                 :          0 :         balanceOf[dst] = balanceOf[dst] + wad;
-      53                 :            : 
-      54                 :          0 :         return true;
-      55                 :            :     }
-      56                 :            : 
-      57                 :            :     function approve(address guy, uint256 wad) public returns (bool) {
-      58                 :          0 :         allowance[msg.sender][guy] = wad;
-      59                 :          0 :         return true;
-      60                 :            :     }
-      61                 :            : 
-      62                 :            :     function mint() public {
-      63                 :          0 :         balanceOf[msg.sender] += 1 ether;
-      64                 :            :     }
-      65                 :            : }
-      66                 :            : 
-      67                 :            : contract Bytes32ERC20WithMetadata is Bytes32ERC20 {
-      68                 :            :     bytes32 public name = 0x4d616b6572000000000000000000000000000000000000000000000000000000;
-      69                 :            :     bytes32 public symbol = 0x4d4b520000000000000000000000000000000000000000000000000000000000;
-      70                 :            :     // TODO: what if this overflows?
-      71                 :            :     uint8 public decimals = 18;
-      72                 :            : 
-      73                 :            :     // no totalSupply field
-      74                 :            :     // uint256 public totalSupply;
-      75                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestPostDepositCall.sol.func-sort-c.html b/coverage/test/TestPostDepositCall.sol.func-sort-c.html deleted file mode 100644 index 0b8fd17d50..0000000000 --- a/coverage/test/TestPostDepositCall.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestPostDepositCall.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestPostDepositCall.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:090.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2Called.onTokenTransfer0
L2Called.postDepositHook0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestPostDepositCall.sol.func.html b/coverage/test/TestPostDepositCall.sol.func.html deleted file mode 100644 index f9299f15e3..0000000000 --- a/coverage/test/TestPostDepositCall.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestPostDepositCall.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestPostDepositCall.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:090.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:060.0 %
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
L2Called.onTokenTransfer0
L2Called.postDepositHook0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestPostDepositCall.sol.gcov.html b/coverage/test/TestPostDepositCall.sol.gcov.html deleted file mode 100644 index 470ee77907..0000000000 --- a/coverage/test/TestPostDepositCall.sol.gcov.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestPostDepositCall.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestPostDepositCall.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:090.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:060.0 %
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : /*
-       4                 :            :  * Copyright 2021, Offchain Labs, Inc.
-       5                 :            :  *
-       6                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
-       7                 :            :  * you may not use this file except in compliance with the License.
-       8                 :            :  * You may obtain a copy of the License at
-       9                 :            :  *
-      10                 :            :  *    http://www.apache.org/licenses/LICENSE-2.0
-      11                 :            :  *
-      12                 :            :  * Unless required by applicable law or agreed to in writing, software
-      13                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
-      14                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-      15                 :            :  * See the License for the specific language governing permissions and
-      16                 :            :  * limitations under the License.
-      17                 :            :  */
-      18                 :            : 
-      19                 :            : pragma solidity ^0.8.0;
-      20                 :            : 
-      21                 :            : import "../libraries/ITransferAndCall.sol";
-      22                 :            : 
-      23                 :            : contract L2Called is ITransferAndCallReceiver {
-      24                 :            :     event Called(uint256 num);
-      25                 :            : 
-      26                 :            :     constructor() {}
-      27                 :            : 
-      28                 :            :     // This function can be anything
-      29                 :            :     function postDepositHook(uint256 num) public {
-      30                 :          0 :         emit Called(num);
-      31                 :            :     }
-      32                 :            : 
-      33                 :            :     function onTokenTransfer(
-      34                 :            :         address, /* sender */
-      35                 :            :         uint256, /* amount */
-      36                 :            :         bytes calldata data
-      37                 :            :     ) external override {
-      38                 :          0 :         uint256 num = abi.decode(data, (uint256));
-      39                 :            : 
-      40         [ #  # ]:          0 :         if (num == 5) {
-      41                 :          0 :             postDepositHook(num);
-      42         [ #  # ]:          0 :         } else if (num == 7) {
-      43                 :          0 :             revert("should fail because 7");
-      44         [ #  # ]:          0 :         } else if (num == 9) {
-      45                 :            :             // this should use all gas
-      46                 :          0 :             while (gasleft() > 0) {}
-      47                 :            :         } else {
-      48                 :          0 :             revert("should fail");
-      49                 :            :         }
-      50                 :            :     }
-      51                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestWETH9.sol.func-sort-c.html b/coverage/test/TestWETH9.sol.func-sort-c.html deleted file mode 100644 index 6b96b51dd5..0000000000 --- a/coverage/test/TestWETH9.sol.func-sort-c.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestWETH9.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestWETH9.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TestWETH9.deposit0
TestWETH9.withdraw0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestWETH9.sol.func.html b/coverage/test/TestWETH9.sol.func.html deleted file mode 100644 index e69ff31d57..0000000000 --- a/coverage/test/TestWETH9.sol.func.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestWETH9.sol - functions - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestWETH9.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- -
- - - - - - - - - - - - - - -

Function Name Sort by function nameHit count Sort by hit count
TestWETH9.deposit0
TestWETH9.withdraw0
-
-
- - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/TestWETH9.sol.gcov.html b/coverage/test/TestWETH9.sol.gcov.html deleted file mode 100644 index 7d0a0015f5..0000000000 --- a/coverage/test/TestWETH9.sol.gcov.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - LCOV - lcov.info - test/TestWETH9.sol - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - test - TestWETH9.sol (source / functions)HitTotalCoverage
Test:lcov.infoLines:030.0 %
Date:2023-04-27 16:26:32Functions:020.0 %
Branches:00-
-
- - - - - - - - -

-
           Branch data     Line data    Source code
-
-       1                 :            : // SPDX-License-Identifier: Apache-2.0
-       2                 :            : 
-       3                 :            : pragma solidity ^0.8.0;
-       4                 :            : 
-       5                 :            : import "../libraries/IWETH9.sol";
-       6                 :            : import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
-       7                 :            : import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
-       8                 :            : 
-       9                 :            : contract TestWETH9 is ERC20, IWETH9 {
-      10                 :            :     constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {}
-      11                 :            : 
-      12                 :            :     function deposit() external payable override {
-      13                 :          0 :         _mint(msg.sender, msg.value);
-      14                 :            :     }
-      15                 :            : 
-      16                 :            :     function withdraw(uint256 _amount) external override {
-      17                 :          0 :         _burn(msg.sender, _amount);
-      18                 :          0 :         payable(address(msg.sender)).transfer(_amount);
-      19                 :            :     }
-      20                 :            : }
-
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/index-sort-b.html b/coverage/test/index-sort-b.html deleted file mode 100644 index c61bc0e5cd..0000000000 --- a/coverage/test/index-sort-b.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - LCOV - lcov.info - test - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - testHitTotalCoverage
Test:lcov.infoLines:156722.4 %
Date:2023-04-27 16:26:32Functions:73718.9 %
Branches:21414.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
TestERC20.sol -
10.0%10.0%
-
10.0 %1 / 1020.0 %1 / 50.0 %0 / 2
TestCustomTokenL1.sol -
0.0%
-
0.0 %0 / 160.0 %0 / 110.0 %0 / 2
TestPostDepositCall.sol -
0.0%
-
0.0 %0 / 90.0 %0 / 20.0 %0 / 6
InboxMock.sol -
87.5%87.5%
-
87.5 %14 / 16100.0 %6 / 650.0 %2 / 4
TestArbCustomTokenBurnFee.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 1-0 / 0
TestWETH9.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 2-0 / 0
TestArbCustomToken.sol -
0.0%
-
0.0 %0 / 40.0 %0 / 6-0 / 0
ArbSysMock.sol -
0.0%
-
0.0 %0 / 40.0 %0 / 1-0 / 0
AddressMappingTest.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
TestBytesParser.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/index-sort-f.html b/coverage/test/index-sort-f.html deleted file mode 100644 index 478c48474b..0000000000 --- a/coverage/test/index-sort-f.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - LCOV - lcov.info - test - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - testHitTotalCoverage
Test:lcov.infoLines:156722.4 %
Date:2023-04-27 16:26:32Functions:73718.9 %
Branches:21414.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
TestArbCustomTokenBurnFee.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 1-0 / 0
ArbSysMock.sol -
0.0%
-
0.0 %0 / 40.0 %0 / 1-0 / 0
AddressMappingTest.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
TestWETH9.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 2-0 / 0
TestPostDepositCall.sol -
0.0%
-
0.0 %0 / 90.0 %0 / 20.0 %0 / 6
TestBytesParser.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
TestArbCustomToken.sol -
0.0%
-
0.0 %0 / 40.0 %0 / 6-0 / 0
TestCustomTokenL1.sol -
0.0%
-
0.0 %0 / 160.0 %0 / 110.0 %0 / 2
TestERC20.sol -
10.0%10.0%
-
10.0 %1 / 1020.0 %1 / 50.0 %0 / 2
InboxMock.sol -
87.5%87.5%
-
87.5 %14 / 16100.0 %6 / 650.0 %2 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/index-sort-l.html b/coverage/test/index-sort-l.html deleted file mode 100644 index def397516c..0000000000 --- a/coverage/test/index-sort-l.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - LCOV - lcov.info - test - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - testHitTotalCoverage
Test:lcov.infoLines:156722.4 %
Date:2023-04-27 16:26:32Functions:73718.9 %
Branches:21414.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
AddressMappingTest.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
TestArbCustomTokenBurnFee.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 1-0 / 0
TestBytesParser.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
TestWETH9.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 2-0 / 0
TestArbCustomToken.sol -
0.0%
-
0.0 %0 / 40.0 %0 / 6-0 / 0
ArbSysMock.sol -
0.0%
-
0.0 %0 / 40.0 %0 / 1-0 / 0
TestPostDepositCall.sol -
0.0%
-
0.0 %0 / 90.0 %0 / 20.0 %0 / 6
TestCustomTokenL1.sol -
0.0%
-
0.0 %0 / 160.0 %0 / 110.0 %0 / 2
TestERC20.sol -
10.0%10.0%
-
10.0 %1 / 1020.0 %1 / 50.0 %0 / 2
InboxMock.sol -
87.5%87.5%
-
87.5 %14 / 16100.0 %6 / 650.0 %2 / 4
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/test/index.html b/coverage/test/index.html deleted file mode 100644 index b85fff851c..0000000000 --- a/coverage/test/index.html +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - LCOV - lcov.info - test - - - - - - - - - - - - - - -
LCOV - code coverage report
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Current view:top level - testHitTotalCoverage
Test:lcov.infoLines:156722.4 %
Date:2023-04-27 16:26:32Functions:73718.9 %
Branches:21414.3 %
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Filename Sort by nameLine Coverage Sort by line coverageFunctions Sort by function coverageBranches Sort by branch coverage
AddressMappingTest.sol -
0.0%
-
0.0 %0 / 10.0 %0 / 1-0 / 0
ArbSysMock.sol -
0.0%
-
0.0 %0 / 40.0 %0 / 1-0 / 0
InboxMock.sol -
87.5%87.5%
-
87.5 %14 / 16100.0 %6 / 650.0 %2 / 4
TestArbCustomToken.sol -
0.0%
-
0.0 %0 / 40.0 %0 / 6-0 / 0
TestArbCustomTokenBurnFee.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 1-0 / 0
TestBytesParser.sol -
0.0%
-
0.0 %0 / 20.0 %0 / 2-0 / 0
TestCustomTokenL1.sol -
0.0%
-
0.0 %0 / 160.0 %0 / 110.0 %0 / 2
TestERC20.sol -
10.0%10.0%
-
10.0 %1 / 1020.0 %1 / 50.0 %0 / 2
TestPostDepositCall.sol -
0.0%
-
0.0 %0 / 90.0 %0 / 20.0 %0 / 6
TestWETH9.sol -
0.0%
-
0.0 %0 / 30.0 %0 / 2-0 / 0
-
-
- - - - -
Generated by: LCOV version 1.16
-
- - - diff --git a/coverage/updown.png b/coverage/updown.png deleted file mode 100644 index aa56a238b3e6c435265250f9266cd1b8caba0f20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^AT}Qd8;}%R+`Ae`*?77*hG?8mPH5^{)z4*}Q$iB}huR`+ diff --git a/lcov.info b/lcov.info deleted file mode 100644 index acfc368967..0000000000 --- a/lcov.info +++ /dev/null @@ -1,1786 +0,0 @@ -TN: -SF:contracts/rpc-utils/MulticallV2.sol -FN:141,ArbMulticall2.aggregate -FNDA:0,ArbMulticall2.aggregate -DA:145,0 -DA:146,0 -DA:147,0 -DA:148,0 -DA:149,0 -BRDA:149,0,0,- -BRDA:149,0,1,- -DA:150,0 -FN:154,ArbMulticall2.blockAndAggregate -FNDA:0,ArbMulticall2.blockAndAggregate -DA:162,0 -FN:165,ArbMulticall2.getBlockHash -FNDA:0,ArbMulticall2.getBlockHash -DA:166,0 -FN:169,ArbMulticall2.getBlockNumber -FNDA:0,ArbMulticall2.getBlockNumber -DA:170,0 -FN:173,ArbMulticall2.getL1BlockNumber -FNDA:0,ArbMulticall2.getL1BlockNumber -DA:174,0 -FN:177,ArbMulticall2.getCurrentBlockCoinbase -FNDA:0,ArbMulticall2.getCurrentBlockCoinbase -DA:178,0 -FN:181,ArbMulticall2.getCurrentBlockDifficulty -FNDA:0,ArbMulticall2.getCurrentBlockDifficulty -DA:182,0 -FN:185,ArbMulticall2.getCurrentBlockGasLimit -FNDA:0,ArbMulticall2.getCurrentBlockGasLimit -DA:186,0 -FN:189,ArbMulticall2.getCurrentBlockTimestamp -FNDA:0,ArbMulticall2.getCurrentBlockTimestamp -DA:190,0 -FN:193,ArbMulticall2.getEthBalance -FNDA:0,ArbMulticall2.getEthBalance -DA:194,0 -FN:197,ArbMulticall2.getLastBlockHash -FNDA:0,ArbMulticall2.getLastBlockHash -DA:198,0 -FN:201,ArbMulticall2.tryAggregateGasRation -FNDA:0,ArbMulticall2.tryAggregateGasRation -DA:205,0 -DA:206,0 -DA:207,0 -DA:208,0 -DA:212,0 -BRDA:212,1,0,- -BRDA:212,1,1,- -DA:213,0 -BRDA:213,2,0,- -BRDA:213,2,1,- -DA:216,0 -FN:220,ArbMulticall2.tryAggregate -FNDA:0,ArbMulticall2.tryAggregate -DA:224,0 -DA:225,0 -DA:226,0 -DA:228,0 -BRDA:228,3,0,- -BRDA:228,3,1,- -DA:229,0 -BRDA:229,4,0,- -BRDA:229,4,1,- -DA:232,0 -FN:236,ArbMulticall2.tryBlockAndAggregate -FNDA:0,ArbMulticall2.tryBlockAndAggregate -DA:244,0 -DA:245,0 -DA:246,0 -FN:25,Multicall2.aggregate -FNDA:0,Multicall2.aggregate -DA:29,0 -DA:30,0 -DA:31,0 -DA:32,0 -DA:33,0 -BRDA:33,0,0,- -BRDA:33,0,1,- -DA:34,0 -FN:38,Multicall2.blockAndAggregate -FNDA:0,Multicall2.blockAndAggregate -DA:46,0 -FN:49,Multicall2.getBlockHash -FNDA:0,Multicall2.getBlockHash -DA:50,0 -FN:53,Multicall2.getBlockNumber -FNDA:0,Multicall2.getBlockNumber -DA:54,0 -FN:57,Multicall2.getCurrentBlockCoinbase -FNDA:0,Multicall2.getCurrentBlockCoinbase -DA:58,0 -FN:61,Multicall2.getCurrentBlockDifficulty -FNDA:0,Multicall2.getCurrentBlockDifficulty -DA:62,0 -FN:65,Multicall2.getCurrentBlockGasLimit -FNDA:0,Multicall2.getCurrentBlockGasLimit -DA:66,0 -FN:69,Multicall2.getCurrentBlockTimestamp -FNDA:0,Multicall2.getCurrentBlockTimestamp -DA:70,0 -FN:73,Multicall2.getEthBalance -FNDA:0,Multicall2.getEthBalance -DA:74,0 -FN:77,Multicall2.getLastBlockHash -FNDA:0,Multicall2.getLastBlockHash -DA:78,0 -FN:81,Multicall2.tryAggregateGasRation -FNDA:0,Multicall2.tryAggregateGasRation -DA:85,0 -DA:86,0 -DA:87,0 -DA:88,0 -DA:92,0 -BRDA:92,1,0,- -BRDA:92,1,1,- -DA:93,0 -BRDA:93,2,0,- -BRDA:93,2,1,- -DA:96,0 -FN:100,Multicall2.tryAggregate -FNDA:0,Multicall2.tryAggregate -DA:104,0 -DA:105,0 -DA:106,0 -DA:108,0 -BRDA:108,3,0,- -BRDA:108,3,1,- -DA:109,0 -BRDA:109,4,0,- -BRDA:109,4,1,- -DA:112,0 -FN:116,Multicall2.tryBlockAndAggregate -FNDA:0,Multicall2.tryBlockAndAggregate -DA:124,0 -DA:125,0 -DA:126,0 -FNF:27 -FNH:0 -LF:63 -LH:0 -BRF:20 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/arbitrum/L2ArbitrumMessenger.sol -FN:30,L2ArbitrumMessenger.sendTxToL1 -FNDA:0,L2ArbitrumMessenger.sendTxToL1 -DA:36,0 -DA:37,0 -DA:38,0 -FNF:1 -FNH:0 -LF:3 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/arbitrum/ReverseArbToken.sol -FN:33,ReverseArbToken.bridgeMint -FNDA:0,ReverseArbToken.bridgeMint -DA:34,0 -FN:37,ReverseArbToken.bridgeBurn -FNDA:0,ReverseArbToken.bridgeBurn -DA:38,0 -FNF:2 -FNH:0 -LF:2 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/arbitrum/StandardArbERC20.sol -FN:43,StandardArbERC20.bridgeInit -FNDA:0,StandardArbERC20.bridgeInit -DA:44,0 -DA:59,0 -DA:60,0 -DA:61,0 -DA:63,0 -DA:74,0 -FN:81,StandardArbERC20.decimals -FNDA:0,StandardArbERC20.decimals -DA:83,0 -BRDA:83,0,0,- -BRDA:83,0,1,- -DA:84,0 -FN:87,StandardArbERC20.name -FNDA:0,StandardArbERC20.name -DA:89,0 -BRDA:89,1,0,- -BRDA:89,1,1,- -DA:90,0 -FN:93,StandardArbERC20.symbol -FNDA:0,StandardArbERC20.symbol -DA:95,0 -BRDA:95,2,0,- -BRDA:95,2,1,- -DA:96,0 -FNF:4 -FNH:0 -LF:12 -LH:0 -BRF:6 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/arbitrum/gateway/L2ArbitrumGateway.sol -FN:64,L2ArbitrumGateway.postUpgradeInit -FNDA:0,L2ArbitrumGateway.postUpgradeInit -DA:67,0 -DA:68,0 -BRDA:68,0,0,- -BRDA:68,0,1,- -FN:72,L2ArbitrumGateway._initialize -FNDA:0,L2ArbitrumGateway._initialize -DA:73,0 -DA:75,0 -BRDA:75,1,0,- -BRDA:75,1,1,- -FN:78,L2ArbitrumGateway.createOutboundTx -FNDA:0,L2ArbitrumGateway.createOutboundTx -DA:87,0 -DA:88,0 -FN:98,L2ArbitrumGateway.getOutboundCalldata -FNDA:0,L2ArbitrumGateway.getOutboundCalldata -DA:105,0 -DA:114,0 -FN:117,L2ArbitrumGateway.outboundTransfer -FNDA:0,L2ArbitrumGateway.outboundTransfer -DA:123,0 -FN:133,L2ArbitrumGateway.outboundTransfer -FNDA:0,L2ArbitrumGateway.outboundTransfer -DA:147,0 -BRDA:147,2,0,- -BRDA:147,2,1,- -DA:149,0 -DA:150,0 -DA:152,0 -BRDA:152,3,0,- -BRDA:152,3,1,- -DA:153,0 -DA:155,0 -DA:156,0 -DA:160,0 -BRDA:160,4,0,- -BRDA:160,4,1,- -DA:162,0 -DA:164,0 -DA:165,0 -BRDA:165,5,0,- -BRDA:165,5,1,- -DA:166,0 -BRDA:166,6,0,- -BRDA:166,6,1,- -DA:168,0 -DA:169,0 -DA:171,0 -FN:174,L2ArbitrumGateway.triggerWithdrawal -FNDA:0,L2ArbitrumGateway.triggerWithdrawal -DA:182,0 -DA:184,0 -DA:189,0 -DA:190,0 -FN:193,L2ArbitrumGateway.outboundEscrowTransfer -FNDA:0,L2ArbitrumGateway.outboundEscrowTransfer -DA:201,0 -DA:204,0 -FN:207,L2ArbitrumGateway.inboundEscrowTransfer -FNDA:0,L2ArbitrumGateway.inboundEscrowTransfer -DA:213,0 -FN:227,L2ArbitrumGateway.finalizeInboundTransfer -FNDA:0,L2ArbitrumGateway.finalizeInboundTransfer -DA:234,0 -DA:237,0 -BRDA:237,7,0,- -BRDA:237,7,1,- -DA:239,0 -DA:242,0 -DA:244,0 -BRDA:244,8,0,- -BRDA:244,8,1,- -DA:245,0 -DA:253,0 -BRDA:253,9,0,- -BRDA:253,9,1,- -DA:259,0 -DA:263,0 -DA:264,0 -BRDA:264,10,0,- -BRDA:264,10,1,- -DA:265,0 -DA:270,0 -DA:271,0 -BRDA:271,11,0,- -BRDA:271,11,1,- -DA:272,0 -DA:276,0 -BRDA:276,12,0,- -BRDA:276,12,1,- -DA:279,0 -DA:280,0 -DA:284,0 -DA:285,0 -DA:287,0 -FNF:10 -FNH:0 -LF:51 -LH:0 -BRF:26 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol -FN:29,L2CustomGateway.initialize -FNDA:0,L2CustomGateway.initialize -DA:30,0 -FN:36,L2CustomGateway.handleNoContract -FNDA:0,L2CustomGateway.handleNoContract -DA:48,0 -DA:49,0 -FN:59,L2CustomGateway.calculateL2TokenAddress -FNDA:0,L2CustomGateway.calculateL2TokenAddress -DA:60,0 -FN:63,L2CustomGateway.registerTokenFromL1 -FNDA:0,L2CustomGateway.registerTokenFromL1 -DA:68,0 -DA:71,0 -DA:72,0 -FNF:4 -FNH:0 -LF:7 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol -FN:30,L2ERC20Gateway.initialize -FNDA:0,L2ERC20Gateway.initialize -DA:35,0 -DA:36,0 -BRDA:36,0,0,- -BRDA:36,0,1,- -DA:37,0 -FN:47,L2ERC20Gateway.calculateL2TokenAddress -FNDA:0,L2ERC20Gateway.calculateL2TokenAddress -DA:55,0 -FN:62,L2ERC20Gateway.cloneableProxyHash -FNDA:0,L2ERC20Gateway.cloneableProxyHash -DA:63,0 -FN:66,L2ERC20Gateway.getUserSalt -FNDA:0,L2ERC20Gateway.getUserSalt -DA:67,0 -FN:78,L2ERC20Gateway.handleNoContract -FNDA:0,L2ERC20Gateway.handleNoContract -DA:86,0 -DA:87,0 -DA:89,0 -DA:91,0 -BRDA:91,1,0,- -BRDA:91,1,1,- -DA:92,0 -DA:97,0 -DA:98,0 -FNF:5 -FNH:0 -LF:13 -LH:0 -BRF:4 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol -FN:39,L2GatewayRouter.initialize -FNDA:0,L2GatewayRouter.initialize -DA:40,0 -FN:43,L2GatewayRouter.setGateway -FNDA:0,L2GatewayRouter.setGateway -DA:48,0 -BRDA:48,0,0,- -BRDA:48,0,1,- -DA:50,0 -DA:51,0 -DA:52,0 -FN:56,L2GatewayRouter.outboundTransfer -FNDA:0,L2GatewayRouter.outboundTransfer -DA:62,0 -FN:65,L2GatewayRouter.setDefaultGateway -FNDA:0,L2GatewayRouter.setDefaultGateway -DA:66,0 -DA:67,0 -FNF:4 -FNH:0 -LF:8 -LH:0 -BRF:2 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/arbitrum/gateway/L2ReverseCustomGateway.sol -FN:39,L2ReverseCustomGateway.inboundEscrowTransfer -FNDA:0,L2ReverseCustomGateway.inboundEscrowTransfer -DA:44,0 -FN:47,L2ReverseCustomGateway.outboundEscrowTransfer -FNDA:0,L2ReverseCustomGateway.outboundEscrowTransfer -DA:52,0 -DA:57,0 -DA:58,0 -DA:59,0 -FNF:2 -FNH:0 -LF:5 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol -FN:32,L2WethGateway.initialize -FNDA:0,L2WethGateway.initialize -DA:38,0 -DA:39,0 -BRDA:39,0,0,- -BRDA:39,0,1,- -DA:40,0 -BRDA:40,1,0,- -BRDA:40,1,1,- -DA:41,0 -DA:42,0 -FN:49,L2WethGateway.handleNoContract -FNDA:0,L2WethGateway.handleNoContract -DA:61,0 -DA:62,0 -FN:72,L2WethGateway.calculateL2TokenAddress -FNDA:0,L2WethGateway.calculateL2TokenAddress -DA:73,0 -BRDA:73,2,0,- -BRDA:73,2,1,- -DA:75,0 -DA:77,0 -FN:80,L2WethGateway.inboundEscrowTransfer -FNDA:0,L2WethGateway.inboundEscrowTransfer -DA:85,0 -DA:86,0 -FN:89,L2WethGateway.createOutboundTx -FNDA:0,L2WethGateway.createOutboundTx -DA:95,0 -DA:96,0 -FNF:5 -FNH:0 -LF:14 -LH:0 -BRF:6 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol -FN:35,L1ArbitrumMessenger.sendTxToL2CustomRefund -FNDA:4,L1ArbitrumMessenger.sendTxToL2CustomRefund -DA:46,4 -FN:61,L1ArbitrumMessenger.sendTxToL2 -FNDA:7,L1ArbitrumMessenger.sendTxToL2 -DA:71,7 -FN:85,L1ArbitrumMessenger.sendTxToL2CustomRefund -FNDA:17,L1ArbitrumMessenger.sendTxToL2CustomRefund -DA:97,17 -DA:109,17 -DA:110,17 -FN:113,L1ArbitrumMessenger.sendTxToL2 -FNDA:13,L1ArbitrumMessenger.sendTxToL2 -DA:124,13 -FN:139,L1ArbitrumMessenger.getBridge -FNDA:10,L1ArbitrumMessenger.getBridge -DA:140,10 -FN:144,L1ArbitrumMessenger.getL2ToL1Sender -FNDA:4,L1ArbitrumMessenger.getL2ToL1Sender -DA:145,4 -DA:146,4 -DA:148,4 -BRDA:148,0,0,- -BRDA:148,0,1,4 -DA:149,4 -FN:166,L1ArbitrumMessenger._createRetryable -FNDA:15,L1ArbitrumMessenger._createRetryable -DA:178,15 -FNF:7 -FNH:7 -LF:12 -LH:12 -BRF:2 -BRH:1 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol -FN:62,L1ArbitrumExtendedGateway.transferExitAndCall -FNDA:5636,L1ArbitrumExtendedGateway.transferExitAndCall -DA:71,5636 -DA:74,5636 -BRDA:74,0,0,2 -BRDA:74,0,1,5634 -DA:76,5634 -BRDA:76,1,0,2 -BRDA:76,1,1,5632 -DA:78,5632 -DA:80,5632 -BRDA:80,2,0,1024 -BRDA:80,2,1,2048 -DA:81,3584 -BRDA:81,3,0,512 -BRDA:81,3,1,3072 -DA:82,3072 -DA:87,3072 -BRDA:87,4,0,1024 -BRDA:87,4,1,2048 -DA:90,4096 -FN:101,L1ArbitrumExtendedGateway.getExternalCall -FNDA:1024,L1ArbitrumExtendedGateway.getExternalCall -DA:107,6662 -DA:108,6662 -DA:113,6662 -BRDA:113,5,0,- -BRDA:113,5,1,- -DA:114,2048 -DA:116,4614 -FN:120,L1ArbitrumExtendedGateway.setRedirectedExit -FNDA:5632,L1ArbitrumExtendedGateway.setRedirectedExit -DA:126,5632 -DA:127,5632 -FN:130,L1ArbitrumExtendedGateway.encodeWithdrawal -FNDA:512,L1ArbitrumExtendedGateway.encodeWithdrawal -DA:136,12806 -FNF:4 -FNH:4 -LF:17 -LH:17 -BRF:12 -BRH:10 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol -FN:76,L1ArbitrumGateway.postUpgradeInit -FNDA:2,L1ArbitrumGateway.postUpgradeInit -DA:79,2 -DA:80,2 -BRDA:80,0,0,2 -BRDA:80,0,1,- -FN:84,L1ArbitrumGateway._initialize -FNDA:13,L1ArbitrumGateway._initialize -DA:89,13 -DA:91,13 -BRDA:91,1,0,- -BRDA:91,1,1,13 -DA:92,13 -BRDA:92,2,0,- -BRDA:92,2,1,13 -DA:93,13 -FN:104,L1ArbitrumGateway.finalizeInboundTransfer -FNDA:6,L1ArbitrumGateway.finalizeInboundTransfer -DA:112,2 -DA:116,2 -BRDA:116,3,0,- -BRDA:116,3,1,2 -DA:118,0 -DA:122,2 -DA:123,2 -DA:125,2 -FN:128,L1ArbitrumGateway.getExternalCall -FNDA:0,L1ArbitrumGateway.getExternalCall -DA:135,0 -DA:136,0 -FN:139,L1ArbitrumGateway.inboundEscrowTransfer -FNDA:2,L1ArbitrumGateway.inboundEscrowTransfer -DA:145,2 -FN:151,L1ArbitrumGateway.createOutboundTxCustomRefund -FNDA:2,L1ArbitrumGateway.createOutboundTxCustomRefund -DA:165,2 -FN:185,L1ArbitrumGateway.createOutboundTx -FNDA:0,L1ArbitrumGateway.createOutboundTx -DA:193,0 -FN:208,L1ArbitrumGateway.outboundTransfer -FNDA:2,L1ArbitrumGateway.outboundTransfer -DA:216,2 -FN:238,L1ArbitrumGateway.outboundTransferCustomRefund -FNDA:12,L1ArbitrumGateway.outboundTransferCustomRefund -DA:247,12 -BRDA:247,4,0,2 -BRDA:247,4,1,10 -DA:250,10 -DA:251,10 -DA:252,10 -DA:254,10 -DA:255,10 -DA:256,10 -BRDA:256,5,0,10 -BRDA:256,5,1,- -DA:258,10 -DA:260,0 -DA:261,0 -DA:264,10 -DA:267,10 -BRDA:267,6,0,2 -BRDA:267,6,1,8 -DA:269,8 -BRDA:269,7,0,2 -BRDA:269,7,1,6 -DA:270,6 -DA:271,6 -BRDA:271,8,0,- -BRDA:271,8,1,6 -DA:273,6 -DA:276,4 -DA:278,4 -DA:289,4 -DA:290,4 -FN:293,L1ArbitrumGateway.outboundEscrowTransfer -FNDA:6,L1ArbitrumGateway.outboundEscrowTransfer -DA:300,6 -DA:301,6 -DA:302,4 -DA:303,4 -FN:306,L1ArbitrumGateway.getOutboundCalldata -FNDA:0,L1ArbitrumGateway.getOutboundCalldata -DA:317,0 -DA:319,0 -DA:328,0 -FN:331,L1ArbitrumGateway.supportsInterface -FNDA:512,L1ArbitrumGateway.supportsInterface -DA:340,512 -FN:359,L1ArbitrumGateway._parseUserEncodedData -FNDA:5,L1ArbitrumGateway._parseUserEncodedData -DA:367,5 -FN:382,L1ArbitrumGateway._initiateDeposit -FNDA:2,L1ArbitrumGateway._initiateDeposit -DA:392,2 -FNF:14 -FNH:11 -LF:48 -LH:39 -BRF:18 -BRH:12 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol -FN:63,L1CustomGateway.outboundTransferCustomRefund -FNDA:0,L1CustomGateway.outboundTransferCustomRefund -DA:72,0 -FN:84,L1CustomGateway.finalizeInboundTransfer -FNDA:0,L1CustomGateway.finalizeInboundTransfer -DA:92,0 -FN:95,L1CustomGateway.initialize -FNDA:6,L1CustomGateway.initialize -DA:101,6 -DA:102,6 -DA:104,6 -DA:106,6 -FN:116,L1CustomGateway.calculateL2TokenAddress -FNDA:7,L1CustomGateway.calculateL2TokenAddress -DA:117,7 -FN:128,L1CustomGateway.registerTokenToL2 -FNDA:0,L1CustomGateway.registerTokenToL2 -DA:134,0 -FN:146,L1CustomGateway.registerTokenToL2 -FNDA:6,L1CustomGateway.registerTokenToL2 -DA:153,6 -BRDA:153,0,0,- -BRDA:153,0,1,6 -DA:158,6 -DA:159,6 -BRDA:159,1,0,- -BRDA:159,1,1,- -DA:161,0 -BRDA:161,2,0,- -BRDA:161,2,1,- -DA:164,6 -DA:166,6 -DA:167,6 -DA:168,6 -DA:169,6 -DA:171,6 -DA:173,6 -DA:179,6 -FN:193,L1CustomGateway.setOwner -FNDA:0,L1CustomGateway.setOwner -DA:194,0 -BRDA:194,3,0,- -BRDA:194,3,1,- -DA:195,0 -FN:208,L1CustomGateway.forceRegisterTokenToL2 -FNDA:0,L1CustomGateway.forceRegisterTokenToL2 -DA:215,0 -BRDA:215,4,0,- -BRDA:215,4,1,- -DA:217,0 -DA:220,0 -DA:221,0 -DA:224,0 -DA:230,0 -FNF:8 -FNH:3 -LF:28 -LH:16 -BRF:10 -BRH:1 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol -FN:57,L1ERC20Gateway.outboundTransferCustomRefund -FNDA:10,L1ERC20Gateway.outboundTransferCustomRefund -DA:66,12 -FN:78,L1ERC20Gateway.finalizeInboundTransfer -FNDA:6,L1ERC20Gateway.finalizeInboundTransfer -DA:86,6 -FN:89,L1ERC20Gateway.initialize -FNDA:7,L1ERC20Gateway.initialize -DA:96,7 -DA:97,7 -BRDA:97,0,0,2 -BRDA:97,0,1,5 -DA:98,5 -BRDA:98,1,0,2 -BRDA:98,1,1,3 -DA:99,3 -DA:100,3 -DA:102,3 -DA:104,3 -FN:113,L1ERC20Gateway.callStatic -FNDA:30,L1ERC20Gateway.callStatic -DA:118,30 -DA:122,30 -DA:123,30 -FN:126,L1ERC20Gateway.getOutboundCalldata -FNDA:6,L1ERC20Gateway.getOutboundCalldata -DA:134,10 -DA:140,10 -DA:149,10 -FN:152,L1ERC20Gateway.calculateL2TokenAddress -FNDA:512,L1ERC20Gateway.calculateL2TokenAddress -DA:153,518 -DA:154,518 -FN:157,L1ERC20Gateway.getSalt -FNDA:518,L1ERC20Gateway.getSalt -DA:159,518 -FNF:7 -FNH:7 -LF:18 -LH:18 -BRF:4 -BRH:4 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/gateway/L1ForceOnlyReverseCustomGateway.sol -FN:27,L1ForceOnlyReverseCustomGateway.registerTokenToL2 -FNDA:0,L1ForceOnlyReverseCustomGateway.registerTokenToL2 -DA:34,0 -FNF:1 -FNH:0 -LF:1 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol -FN:50,L1GatewayRouter.initialize -FNDA:4,L1GatewayRouter.initialize -DA:57,4 -DA:58,2 -DA:59,2 -DA:60,2 -FN:63,L1GatewayRouter.setDefaultGateway -FNDA:1,L1GatewayRouter.setDefaultGateway -DA:69,1 -DA:71,1 -DA:73,1 -DA:75,1 -BRDA:75,0,0,- -BRDA:75,0,1,1 -DA:76,1 -DA:79,1 -DA:84,1 -FN:100,L1GatewayRouter.setOwner -FNDA:258,L1GatewayRouter.setOwner -DA:101,257 -BRDA:101,1,0,1 -BRDA:101,1,1,256 -DA:103,256 -FN:106,L1GatewayRouter._setGateways -FNDA:7,L1GatewayRouter._setGateways -DA:114,7 -BRDA:114,2,0,- -BRDA:114,2,1,7 -DA:116,7 -DA:117,8 -DA:118,8 -DA:120,8 -BRDA:120,3,0,- -BRDA:120,3,1,6 -DA:124,7 -BRDA:124,4,0,1 -BRDA:124,4,1,6 -DA:128,6 -DA:132,6 -DA:138,6 -FN:162,L1GatewayRouter.setGateway -FNDA:1,L1GatewayRouter.setGateway -DA:168,1 -FN:180,L1GatewayRouter.setGateway -FNDA:7,L1GatewayRouter.setGateway -DA:187,8 -BRDA:187,5,0,1 -BRDA:187,5,1,7 -DA:192,7 -BRDA:192,6,0,1 -BRDA:192,6,1,6 -DA:194,6 -DA:195,6 -BRDA:195,7,0,1 -BRDA:195,7,1,- -DA:197,1 -BRDA:197,8,0,1 -BRDA:197,8,1,- -DA:200,5 -DA:201,5 -DA:203,5 -DA:204,5 -DA:206,5 -FN:217,L1GatewayRouter.setGateways -FNDA:3,L1GatewayRouter.setGateways -DA:226,2 -FN:230,L1GatewayRouter.outboundTransfer -FNDA:0,L1GatewayRouter.outboundTransfer -DA:238,0 -FN:259,L1GatewayRouter.outboundTransferCustomRefund -FNDA:0,L1GatewayRouter.outboundTransferCustomRefund -DA:268,0 -DA:269,0 -DA:274,0 -DA:276,0 -FN:294,L1GatewayRouter.supportsInterface -FNDA:256,L1GatewayRouter.supportsInterface -DA:302,256 -FNF:10 -FNH:8 -LF:40 -LH:35 -BRF:18 -BRH:13 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol -FN:15,L1OrbitERC20Gateway._parseUserEncodedData -FNDA:5,L1OrbitERC20Gateway._parseUserEncodedData -DA:23,5 -FN:29,L1OrbitERC20Gateway._initiateDeposit -FNDA:2,L1OrbitERC20Gateway._initiateDeposit -DA:39,2 -FN:56,L1OrbitERC20Gateway._createRetryable -FNDA:2,L1OrbitERC20Gateway._createRetryable -DA:68,2 -FNF:3 -FNH:3 -LF:3 -LH:3 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol -FN:37,L1ReverseCustomGateway.inboundEscrowTransfer -FNDA:0,L1ReverseCustomGateway.inboundEscrowTransfer -DA:42,0 -FN:45,L1ReverseCustomGateway.outboundEscrowTransfer -FNDA:0,L1ReverseCustomGateway.outboundEscrowTransfer -DA:50,0 -DA:53,0 -FNF:2 -FNH:0 -LF:3 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol -FN:34,L1WethGateway.initialize -FNDA:0,L1WethGateway.initialize -DA:41,0 -DA:42,0 -BRDA:42,0,0,- -BRDA:42,0,1,- -DA:43,0 -BRDA:43,1,0,- -BRDA:43,1,1,- -DA:44,0 -DA:45,0 -FN:48,L1WethGateway.createOutboundTxCustomRefund -FNDA:0,L1WethGateway.createOutboundTxCustomRefund -DA:57,0 -FN:76,L1WethGateway.outboundEscrowTransfer -FNDA:0,L1WethGateway.outboundEscrowTransfer -DA:81,0 -DA:82,0 -DA:85,0 -FN:88,L1WethGateway.inboundEscrowTransfer -FNDA:0,L1WethGateway.inboundEscrowTransfer -DA:93,0 -DA:94,0 -FN:104,L1WethGateway.calculateL2TokenAddress -FNDA:0,L1WethGateway.calculateL2TokenAddress -DA:105,0 -BRDA:105,2,0,- -BRDA:105,2,1,- -DA:107,0 -DA:109,0 -FN:115,L1WethGateway.setRedirectedExit -FNDA:0,L1WethGateway.setRedirectedExit -DA:121,0 -FNF:6 -FNH:0 -LF:15 -LH:0 -BRF:6 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/AddressAliasHelper.sol -FN:28,AddressAliasHelper.applyL1ToL2Alias -FNDA:0,AddressAliasHelper.applyL1ToL2Alias -DA:30,0 -FN:38,AddressAliasHelper.undoL1ToL2Alias -FNDA:0,AddressAliasHelper.undoL1ToL2Alias -DA:40,0 -FNF:2 -FNH:0 -LF:2 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/BytesLib.sol -FN:15,BytesLib.toAddress -FNDA:0,BytesLib.toAddress -DA:16,0 -BRDA:16,0,0,- -BRDA:16,0,1,- -DA:17,0 -DA:20,0 -DA:23,0 -FN:26,BytesLib.toUint8 -FNDA:0,BytesLib.toUint8 -DA:27,0 -BRDA:27,1,0,- -BRDA:27,1,1,- -DA:28,0 -DA:31,0 -DA:34,0 -FN:37,BytesLib.toUint -FNDA:0,BytesLib.toUint -DA:38,0 -BRDA:38,2,0,- -BRDA:38,2,1,- -DA:39,0 -DA:42,0 -DA:45,0 -FN:48,BytesLib.toBytes32 -FNDA:0,BytesLib.toBytes32 -DA:49,0 -BRDA:49,3,0,- -BRDA:49,3,1,- -DA:50,0 -DA:53,0 -DA:56,0 -FNF:4 -FNH:0 -LF:16 -LH:0 -BRF:8 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/BytesParser.sol -FN:26,BytesParser.toUint8 -FNDA:0,BytesParser.toUint8 -DA:27,0 -BRDA:27,0,0,- -BRDA:27,0,1,- -DA:28,0 -DA:31,0 -DA:32,0 -BRDA:32,1,0,- -BRDA:32,1,1,- -DA:33,0 -DA:35,0 -DA:36,0 -FN:39,BytesParser.toString -FNDA:0,BytesParser.toString -DA:40,0 -BRDA:40,2,0,- -BRDA:40,2,1,- -DA:41,0 -DA:43,0 -BRDA:43,3,0,- -BRDA:43,3,1,- -DA:45,0 -BRDA:45,4,0,- -BRDA:45,4,1,- -DA:46,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:56,0 -DA:57,0 -DA:58,0 -DA:63,0 -DA:67,0 -DA:68,0 -FNF:2 -FNH:0 -LF:21 -LH:0 -BRF:10 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/ClonableBeaconProxy.sol -FN:27,BeaconProxyFactory.initialize -FNDA:0,BeaconProxyFactory.initialize -DA:28,0 -BRDA:28,0,0,- -BRDA:28,0,1,- -DA:29,0 -BRDA:29,1,0,- -BRDA:29,1,1,- -DA:30,0 -FN:33,BeaconProxyFactory.getSalt -FNDA:0,BeaconProxyFactory.getSalt -DA:34,0 -FN:37,BeaconProxyFactory.createProxy -FNDA:0,BeaconProxyFactory.createProxy -DA:39,0 -DA:40,0 -DA:41,0 -FN:44,BeaconProxyFactory.calculateExpectedAddress -FNDA:0,BeaconProxyFactory.calculateExpectedAddress -DA:49,0 -DA:50,0 -FN:53,BeaconProxyFactory.calculateExpectedAddress -FNDA:0,BeaconProxyFactory.calculateExpectedAddress -DA:54,0 -FNF:5 -FNH:0 -LF:10 -LH:0 -BRF:4 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/Cloneable.sol -FN:32,Cloneable.isMaster -FNDA:0,Cloneable.isMaster -DA:33,0 -FN:36,Cloneable.safeSelfDestruct -FNDA:0,Cloneable.safeSelfDestruct -DA:37,0 -BRDA:37,0,0,- -BRDA:37,0,1,- -DA:38,0 -FNF:2 -FNH:0 -LF:3 -LH:0 -BRF:2 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/ERC165.sol -FN:29,ERC165.supportsInterface -FNDA:768,ERC165.supportsInterface -DA:30,768 -FNF:1 -FNH:1 -LF:1 -LH:1 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/ERC20Upgradeable.sol -FN:45,ERC20Upgradeable.__ERC20_init -FNDA:0,ERC20Upgradeable.__ERC20_init -DA:46,0 -FN:49,ERC20Upgradeable.__ERC20_init_unchained -FNDA:0,ERC20Upgradeable.__ERC20_init_unchained -DA:53,0 -DA:54,0 -DA:55,0 -FN:61,ERC20Upgradeable.name -FNDA:10,ERC20Upgradeable.name -DA:62,10 -FN:69,ERC20Upgradeable.symbol -FNDA:10,ERC20Upgradeable.symbol -DA:70,10 -FN:86,ERC20Upgradeable.decimals -FNDA:10,ERC20Upgradeable.decimals -DA:87,10 -FN:93,ERC20Upgradeable.totalSupply -FNDA:0,ERC20Upgradeable.totalSupply -DA:94,0 -FN:100,ERC20Upgradeable.balanceOf -FNDA:34,ERC20Upgradeable.balanceOf -DA:101,34 -FN:112,ERC20Upgradeable.transfer -FNDA:2,ERC20Upgradeable.transfer -DA:113,2 -DA:114,2 -DA:115,2 -FN:121,ERC20Upgradeable.allowance -FNDA:0,ERC20Upgradeable.allowance -DA:125,6 -FN:138,ERC20Upgradeable.approve -FNDA:4,ERC20Upgradeable.approve -DA:139,4 -DA:140,4 -DA:141,4 -FN:160,ERC20Upgradeable.transferFrom -FNDA:6,ERC20Upgradeable.transferFrom -DA:165,6 -DA:166,6 -DA:167,4 -DA:168,4 -FN:183,ERC20Upgradeable.increaseAllowance -FNDA:0,ERC20Upgradeable.increaseAllowance -DA:184,0 -DA:185,0 -DA:186,0 -FN:203,ERC20Upgradeable.decreaseAllowance -FNDA:0,ERC20Upgradeable.decreaseAllowance -DA:207,0 -DA:208,0 -DA:209,0 -BRDA:209,0,0,- -BRDA:209,0,1,- -DA:211,0 -DA:214,0 -FN:231,ERC20Upgradeable._transfer -FNDA:6,ERC20Upgradeable._transfer -DA:232,6 -BRDA:232,1,0,- -BRDA:232,1,1,6 -DA:233,6 -BRDA:233,2,0,- -BRDA:233,2,1,6 -DA:235,6 -DA:237,6 -DA:238,6 -BRDA:238,3,0,- -BRDA:238,3,1,6 -DA:240,6 -DA:243,6 -DA:246,6 -DA:248,6 -FN:260,ERC20Upgradeable._mint -FNDA:2,ERC20Upgradeable._mint -DA:261,2 -BRDA:261,4,0,- -BRDA:261,4,1,2 -DA:263,2 -DA:265,2 -DA:268,2 -DA:270,2 -DA:272,2 -FN:286,ERC20Upgradeable._burn -FNDA:0,ERC20Upgradeable._burn -DA:287,0 -BRDA:287,5,0,- -BRDA:287,5,1,- -DA:289,0 -DA:291,0 -DA:292,0 -BRDA:292,6,0,- -BRDA:292,6,1,- -DA:294,0 -DA:296,0 -DA:299,0 -DA:301,0 -FN:317,ERC20Upgradeable._approve -FNDA:8,ERC20Upgradeable._approve -DA:318,8 -BRDA:318,7,0,- -BRDA:318,7,1,8 -DA:319,8 -BRDA:319,8,0,- -BRDA:319,8,1,8 -DA:321,8 -DA:322,8 -FN:332,ERC20Upgradeable._setupDecimals -FNDA:0,ERC20Upgradeable._setupDecimals -DA:333,0 -FN:344,ERC20Upgradeable._spendAllowance -FNDA:6,ERC20Upgradeable._spendAllowance -DA:345,6 -DA:346,6 -BRDA:346,9,0,2 -BRDA:346,9,1,4 -DA:347,6 -BRDA:347,10,0,2 -BRDA:347,10,1,4 -DA:349,4 -FN:368,ERC20Upgradeable._beforeTokenTransfer -FNDA:8,ERC20Upgradeable._beforeTokenTransfer -FN:384,ERC20Upgradeable._afterTokenTransfer -FNDA:8,ERC20Upgradeable._afterTokenTransfer -FNF:21 -FNH:13 -LF:60 -LH:38 -BRF:22 -BRH:10 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/L2CustomGatewayToken.sol -FN:36,L2CustomGatewayToken.initialize -FNDA:0,L2CustomGatewayToken.initialize -DA:43,0 -FNF:1 -FNH:0 -LF:1 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/L2GatewayToken.sol -FN:46,L2GatewayToken._initialize -FNDA:0,L2GatewayToken._initialize -DA:53,0 -BRDA:53,0,0,- -BRDA:53,0,1,- -DA:54,0 -BRDA:54,1,0,- -BRDA:54,1,1,- -DA:55,0 -DA:56,0 -DA:58,0 -FN:66,L2GatewayToken.bridgeMint -FNDA:0,L2GatewayToken.bridgeMint -DA:67,0 -FN:76,L2GatewayToken.bridgeBurn -FNDA:0,L2GatewayToken.bridgeBurn -DA:77,0 -FNF:3 -FNH:0 -LF:7 -LH:0 -BRF:4 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/ProxyUtil.sol -FN:22,ProxyUtil.getProxyAdmin -FNDA:0,ProxyUtil.getProxyAdmin -DA:26,0 -DA:28,0 -FNF:1 -FNH:0 -LF:2 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/TransferAndCallToken.sol -FN:20,TransferAndCallToken.transferAndCall -FNDA:0,TransferAndCallToken.transferAndCall -DA:25,0 -DA:26,0 -DA:27,0 -BRDA:27,0,0,- -BRDA:27,0,1,- -DA:28,0 -DA:30,0 -FN:35,TransferAndCallToken.contractFallback -FNDA:0,TransferAndCallToken.contractFallback -DA:40,0 -DA:41,0 -FN:44,TransferAndCallToken.isContract -FNDA:0,TransferAndCallToken.isContract -DA:45,0 -DA:47,0 -DA:49,0 -FNF:3 -FNH:0 -LF:10 -LH:0 -BRF:2 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/Whitelist.sol -FN:33,WhitelistConsumer.updateWhitelistSource -FNDA:0,WhitelistConsumer.updateWhitelistSource -DA:34,0 -BRDA:34,0,0,- -BRDA:34,0,1,- -DA:35,0 -DA:36,0 -FN:56,Whitelist.setOwner -FNDA:0,Whitelist.setOwner -DA:57,0 -DA:58,0 -FN:61,Whitelist.setWhitelist -FNDA:0,Whitelist.setWhitelist -DA:62,0 -BRDA:62,0,0,- -BRDA:62,0,1,- -DA:64,0 -DA:65,0 -FN:70,Whitelist.triggerConsumers -FNDA:0,Whitelist.triggerConsumers -DA:71,0 -DA:72,0 -DA:74,0 -FNF:4 -FNH:0 -LF:11 -LH:0 -BRF:4 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/aeERC20.sol -FN:35,aeERC20._initialize -FNDA:0,aeERC20._initialize -DA:40,0 -DA:41,0 -DA:42,0 -FNF:1 -FNH:0 -LF:3 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/aeWETH.sol -FN:26,aeWETH.initialize -FNDA:0,aeWETH.initialize -DA:33,0 -FN:36,aeWETH.bridgeMint -FNDA:0,aeWETH.bridgeMint -DA:41,0 -FN:44,aeWETH.bridgeBurn -FNDA:0,aeWETH.bridgeBurn -DA:45,0 -DA:46,0 -DA:47,0 -BRDA:47,0,0,- -BRDA:47,0,1,- -FN:50,aeWETH.deposit -FNDA:0,aeWETH.deposit -DA:51,0 -FN:54,aeWETH.withdraw -FNDA:0,aeWETH.withdraw -DA:55,0 -FN:58,aeWETH.depositTo -FNDA:0,aeWETH.depositTo -DA:59,0 -FN:62,aeWETH.withdrawTo -FNDA:0,aeWETH.withdrawTo -DA:63,0 -DA:64,0 -DA:65,0 -BRDA:65,1,0,- -BRDA:65,1,1,- -FNF:7 -FNH:0 -LF:11 -LH:0 -BRF:4 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/draft-ERC20PermitUpgradeable.sol -FN:50,ERC20PermitUpgradeable.__ERC20Permit_init -FNDA:0,ERC20PermitUpgradeable.__ERC20Permit_init -DA:51,0 -FN:54,ERC20PermitUpgradeable.__ERC20Permit_init_unchained -FNDA:0,ERC20PermitUpgradeable.__ERC20Permit_init_unchained -FN:59,ERC20PermitUpgradeable.permit -FNDA:0,ERC20PermitUpgradeable.permit -DA:68,0 -BRDA:68,0,0,- -BRDA:68,0,1,- -DA:70,0 -DA:74,0 -DA:76,0 -DA:77,0 -BRDA:77,1,0,- -BRDA:77,1,1,- -DA:79,0 -FN:85,ERC20PermitUpgradeable.nonces -FNDA:0,ERC20PermitUpgradeable.nonces -DA:86,0 -FN:93,ERC20PermitUpgradeable.DOMAIN_SEPARATOR -FNDA:0,ERC20PermitUpgradeable.DOMAIN_SEPARATOR -DA:94,0 -FN:102,ERC20PermitUpgradeable._useNonce -FNDA:0,ERC20PermitUpgradeable._useNonce -DA:103,0 -DA:104,0 -DA:105,0 -FNF:6 -FNH:0 -LF:12 -LH:0 -BRF:4 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/gateway/GatewayMessageHandler.sol -FN:25,GatewayMessageHandler.encodeToL2GatewayMsg -FNDA:0,GatewayMessageHandler.encodeToL2GatewayMsg -DA:30,0 -FN:33,GatewayMessageHandler.parseFromL1GatewayMsg -FNDA:0,GatewayMessageHandler.parseFromL1GatewayMsg -DA:39,0 -FN:44,GatewayMessageHandler.encodeFromL2GatewayMsg -FNDA:0,GatewayMessageHandler.encodeFromL2GatewayMsg -DA:49,0 -FN:52,GatewayMessageHandler.parseToL1GatewayMsg -FNDA:0,GatewayMessageHandler.parseToL1GatewayMsg -DA:58,0 -FN:63,GatewayMessageHandler.encodeFromRouterToGateway -FNDA:0,GatewayMessageHandler.encodeFromRouterToGateway -DA:69,0 -FN:72,GatewayMessageHandler.parseFromRouterToGateway -FNDA:0,GatewayMessageHandler.parseFromRouterToGateway -DA:78,0 -FNF:6 -FNH:0 -LF:6 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/gateway/GatewayRouter.sol -FN:39,GatewayRouter.postUpgradeInit -FNDA:1,GatewayRouter.postUpgradeInit -DA:42,1 -DA:43,1 -BRDA:43,0,0,1 -BRDA:43,0,1,- -FN:47,GatewayRouter._initialize -FNDA:4,GatewayRouter._initialize -DA:53,4 -BRDA:53,1,0,- -BRDA:53,1,1,4 -DA:54,4 -DA:56,2 -FN:59,GatewayRouter.finalizeInboundTransfer -FNDA:0,GatewayRouter.finalizeInboundTransfer -DA:66,0 -FN:69,GatewayRouter.outboundTransfer -FNDA:0,GatewayRouter.outboundTransfer -DA:79,0 -DA:80,0 -DA:85,0 -DA:86,0 -FN:97,GatewayRouter.getOutboundCalldata -FNDA:0,GatewayRouter.getOutboundCalldata -DA:104,0 -DA:105,0 -FN:108,GatewayRouter.getGateway -FNDA:0,GatewayRouter.getGateway -DA:109,6 -DA:111,6 -BRDA:111,2,0,5 -BRDA:111,2,1,6 -DA:113,5 -DA:116,6 -BRDA:116,3,0,5 -BRDA:116,3,1,1 -DA:118,5 -DA:121,0 -FN:124,GatewayRouter.calculateL2TokenAddress -FNDA:0,GatewayRouter.calculateL2TokenAddress -DA:131,0 -DA:132,0 -BRDA:132,4,0,- -BRDA:132,4,1,- -DA:133,0 -DA:135,0 -FNF:7 -FNH:2 -LF:22 -LH:10 -BRF:10 -BRH:6 -end_of_record -TN: -SF:contracts/tokenbridge/libraries/gateway/TokenGateway.sol -FN:36,TokenGateway._initialize -FNDA:17,TokenGateway._initialize -DA:40,17 -BRDA:40,0,0,1 -BRDA:40,0,1,16 -DA:41,16 -BRDA:41,1,0,1 -BRDA:41,1,1,15 -DA:42,15 -DA:43,15 -FN:46,TokenGateway.isRouter -FNDA:22,TokenGateway.isRouter -DA:47,22 -FNF:2 -FNH:2 -LF:5 -LH:5 -BRF:4 -BRH:4 -end_of_record -TN: -SF:contracts/tokenbridge/test/AddressMappingTest.sol -FN:25,AddressMappingTest.getL1AddressTest -FNDA:0,AddressMappingTest.getL1AddressTest -DA:26,0 -FNF:1 -FNH:0 -LF:1 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/test/ArbSysMock.sol -FN:7,ArbSysMock.sendTxToL1 -FNDA:0,ArbSysMock.sendTxToL1 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -FNF:1 -FNH:0 -LF:4 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/test/InboxMock.sol -FN:49,InboxMock.createRetryableTicket -FNDA:15,InboxMock.createRetryableTicket -DA:59,15 -BRDA:59,0,0,- -BRDA:59,0,1,15 -DA:60,0 -DA:62,15 -DA:63,15 -DA:64,15 -DA:65,15 -FN:31,AbsInboxMock.bridge -FNDA:14,AbsInboxMock.bridge -DA:32,14 -FN:35,AbsInboxMock.activeOutbox -FNDA:4,AbsInboxMock.activeOutbox -DA:36,4 -FN:39,AbsInboxMock.setL2ToL1Sender -FNDA:4,AbsInboxMock.setL2ToL1Sender -DA:40,4 -FN:43,AbsInboxMock.l2ToL1Sender -FNDA:4,AbsInboxMock.l2ToL1Sender -DA:44,4 -FN:80,ERC20InboxMock.createRetryableTicket -FNDA:2,ERC20InboxMock.createRetryableTicket -DA:92,2 -BRDA:92,0,0,- -BRDA:92,0,1,2 -DA:93,0 -DA:96,2 -DA:97,2 -DA:98,2 -DA:107,2 -FNF:6 -FNH:6 -LF:16 -LH:14 -BRF:4 -BRH:2 -end_of_record -TN: -SF:contracts/tokenbridge/test/TestArbCustomToken.sol -FN:54,MintableTestArbCustomToken.userMint -FNDA:0,MintableTestArbCustomToken.userMint -DA:55,0 -FN:40,TestArbCustomToken.someWackyCustomStuff -FNDA:0,TestArbCustomToken.someWackyCustomStuff -FN:42,TestArbCustomToken.bridgeMint -FNDA:0,TestArbCustomToken.bridgeMint -DA:43,0 -FN:46,TestArbCustomToken.bridgeBurn -FNDA:0,TestArbCustomToken.bridgeBurn -DA:47,0 -FN:74,ReverseTestArbCustomToken.someWackyCustomStuff -FNDA:0,ReverseTestArbCustomToken.someWackyCustomStuff -FN:76,ReverseTestArbCustomToken.mint -FNDA:0,ReverseTestArbCustomToken.mint -DA:77,0 -FNF:6 -FNH:0 -LF:4 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/test/TestArbCustomTokenBurnFee.sol -FN:31,TestArbCustomTokenBurnFee._burn -FNDA:0,TestArbCustomTokenBurnFee._burn -DA:32,0 -DA:33,0 -FNF:1 -FNH:0 -LF:2 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/test/TestBytesParser.sol -FN:24,TestBytesParser.bytesToString -FNDA:0,TestBytesParser.bytesToString -DA:29,0 -FN:32,TestBytesParser.bytesToUint8 -FNDA:0,TestBytesParser.bytesToUint8 -DA:33,0 -FNF:2 -FNH:0 -LF:2 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/test/TestCustomTokenL1.sol -FN:144,ReverseTestCustomTokenL1.bridgeBurn -FNDA:0,ReverseTestCustomTokenL1.bridgeBurn -DA:149,0 -FN:152,ReverseTestCustomTokenL1.balanceOf -FNDA:0,ReverseTestCustomTokenL1.balanceOf -DA:158,0 -FN:161,ReverseTestCustomTokenL1.transferFrom -FNDA:0,ReverseTestCustomTokenL1.transferFrom -DA:166,0 -FN:114,MintableTestCustomTokenL1.bridgeMint -FNDA:0,MintableTestCustomTokenL1.bridgeMint -DA:119,0 -FN:122,MintableTestCustomTokenL1.balanceOf -FNDA:0,MintableTestCustomTokenL1.balanceOf -DA:129,0 -FN:132,MintableTestCustomTokenL1.transferFrom -FNDA:0,MintableTestCustomTokenL1.transferFrom -DA:137,0 -FN:43,TestCustomTokenL1.mint -FNDA:0,TestCustomTokenL1.mint -DA:44,0 -FN:47,TestCustomTokenL1.transferFrom -FNDA:0,TestCustomTokenL1.transferFrom -DA:52,0 -FN:55,TestCustomTokenL1.balanceOf -FNDA:0,TestCustomTokenL1.balanceOf -DA:62,0 -FN:66,TestCustomTokenL1.isArbitrumEnabled -FNDA:0,TestCustomTokenL1.isArbitrumEnabled -DA:67,0 -BRDA:67,0,0,- -BRDA:67,0,1,- -DA:68,0 -FN:71,TestCustomTokenL1.registerTokenOnL2 -FNDA:0,TestCustomTokenL1.registerTokenOnL2 -DA:83,0 -DA:84,0 -DA:86,0 -DA:94,0 -DA:102,0 -FNF:11 -FNH:0 -LF:16 -LH:0 -BRF:2 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/test/TestERC20.sol -FN:28,TestERC20.mint -FNDA:2,TestERC20.mint -DA:29,2 -FN:38,Bytes32ERC20.transfer -FNDA:0,Bytes32ERC20.transfer -DA:39,0 -FN:42,Bytes32ERC20.transferFrom -FNDA:0,Bytes32ERC20.transferFrom -DA:47,0 -BRDA:47,0,0,- -BRDA:47,0,1,- -DA:48,0 -DA:51,0 -DA:52,0 -DA:54,0 -FN:57,Bytes32ERC20.approve -FNDA:0,Bytes32ERC20.approve -DA:58,0 -DA:59,0 -FN:62,Bytes32ERC20.mint -FNDA:0,Bytes32ERC20.mint -DA:63,0 -FNF:5 -FNH:1 -LF:10 -LH:1 -BRF:2 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/test/TestPostDepositCall.sol -FN:29,L2Called.postDepositHook -FNDA:0,L2Called.postDepositHook -DA:30,0 -FN:33,L2Called.onTokenTransfer -FNDA:0,L2Called.onTokenTransfer -DA:38,0 -DA:40,0 -BRDA:40,0,0,- -BRDA:40,0,1,- -DA:41,0 -DA:42,0 -BRDA:42,1,0,- -BRDA:42,1,1,- -DA:43,0 -DA:44,0 -BRDA:44,2,0,- -BRDA:44,2,1,- -DA:46,0 -DA:48,0 -FNF:2 -FNH:0 -LF:9 -LH:0 -BRF:6 -BRH:0 -end_of_record -TN: -SF:contracts/tokenbridge/test/TestWETH9.sol -FN:12,TestWETH9.deposit -FNDA:0,TestWETH9.deposit -DA:13,0 -FN:16,TestWETH9.withdraw -FNDA:0,TestWETH9.withdraw -DA:17,0 -DA:18,0 -FNF:2 -FNH:0 -LF:3 -LH:0 -BRF:0 -BRH:0 -end_of_record -TN: -SF:test-foundry/L1ArbitrumExtendedGateway.t.sol -FN:315,TestExitReceiver.onExitTransfer -FNDA:3072,TestExitReceiver.onExitTransfer -DA:320,3072 -DA:321,3072 -FNF:1 -FNH:1 -LF:2 -LH:2 -BRF:0 -BRH:0 -end_of_record diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 913a629da4..18478a8970 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -26,6 +26,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { uint256 public maxGas = 1000000000; uint256 public gasPriceBid = 3; uint256 public retryableCost = maxSubmissionCost + maxGas * gasPriceBid; + address public creditBackAddress = makeAddr("creditBackAddress"); function setUp() public { inbox = address(new InboxMock()); @@ -124,6 +125,47 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } + function test_setDefaultGateway_AddressZero() public { + address newL1DefaultGateway = address(0); + + // event checkers + vm.expectEmit(true, true, true, true); + emit DefaultGatewayUpdated(address(newL1DefaultGateway)); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Router), + counterpartGateway, + 0, + maxGas, + abi.encodeWithSelector(L2GatewayRouter.setDefaultGateway.selector, address(0)) + ); + + // set it + vm.prank(owner); + uint256 seqNum = l1Router.setDefaultGateway{ value: retryableCost }( + newL1DefaultGateway, + maxGas, + gasPriceBid, + maxSubmissionCost + ); + + /// checks + assertEq( + l1Router.defaultGateway(), + address(newL1DefaultGateway), + "Invalid newL1DefaultGateway" + ); + + assertEq(seqNum, 0, "Invalid seqNum"); + } + function test_setGateway() public { // create gateway L1CustomGateway customGateway = new L1CustomGateway(); @@ -149,9 +191,6 @@ contract L1GatewayRouterTest is GatewayRouterTest { makeAddr("creditBackAddress") ); - // set gateway params - address creditBackAddress = makeAddr("creditBackAddress"); - // expect events vm.expectEmit(true, true, true, true); emit GatewaySet(address(customToken), address(customGateway)); @@ -160,7 +199,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { emit TicketData(maxSubmissionCost); vm.expectEmit(true, true, true, true); - emit RefundAddresses(creditBackAddress, creditBackAddress); + emit RefundAddresses(address(customToken), address(customToken)); vm.expectEmit(true, true, true, true); address[] memory _tokenArr = new address[](1); @@ -181,8 +220,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { address(customGateway), maxGas, gasPriceBid, - maxSubmissionCost, - creditBackAddress + maxSubmissionCost ); ///// checks @@ -221,12 +259,6 @@ contract L1GatewayRouterTest is GatewayRouterTest { makeAddr("creditBackAddress") ); - // set gateway params - uint256 maxSubmissionCost = 40000; - uint256 maxGas = 1000000000; - uint256 gasPrice = 3; - uint256 value = maxSubmissionCost + maxGas * gasPrice; - // expect events vm.expectEmit(true, true, true, true); emit GatewaySet(address(customToken), address(customGateway)); @@ -235,7 +267,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { emit TicketData(maxSubmissionCost); vm.expectEmit(true, true, true, true); - emit RefundAddresses(address(customToken), address(customToken)); + emit RefundAddresses(creditBackAddress, creditBackAddress); vm.expectEmit(true, true, true, true); address[] memory _tokenArr = new address[](1); @@ -256,7 +288,8 @@ contract L1GatewayRouterTest is GatewayRouterTest { address(customGateway), maxGas, gasPriceBid, - maxSubmissionCost + maxSubmissionCost, + creditBackAddress ); ///// checks @@ -328,13 +361,6 @@ contract L1GatewayRouterTest is GatewayRouterTest { abi.encode(uint8(0xb1)) ); - // retryable params - uint256 maxSubmissionCost = 40000; - uint256 maxGas = 1000000000; - uint256 gasPrice = 3; - uint256 value = maxSubmissionCost + maxGas * gasPrice; - address creditBackAddress = makeAddr("creditBackAddress"); - // register token to gateway vm.prank(token); L1CustomGateway(initialGateway).registerTokenToL2{ value: retryableCost }( @@ -391,12 +417,6 @@ contract L1GatewayRouterTest is GatewayRouterTest { } function test_setGateways() public { - // retryables params - uint256 maxSubmissionCost = 40000; - uint256 maxGas = 1000000000; - uint256 gasPrice = 3; - uint256 value = maxSubmissionCost + maxGas * gasPrice; - // create tokens and gateways address[] memory tokens = new address[](2); tokens[0] = address(new ERC20("1", "1")); @@ -475,6 +495,25 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } + function test_setGateways_revert_WrongLength() public { + address[] memory tokens = new address[](2); + tokens[0] = address(new ERC20("1", "1")); + tokens[1] = address(new ERC20("2", "2")); + address[] memory gateways = new address[](1); + gateways[0] = address(new L1CustomGateway()); + + /// set gateways + vm.prank(owner); + vm.expectRevert("WRONG_LENGTH"); + l1Router.setGateways{ value: retryableCost }( + tokens, + gateways, + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + function test_setGateways_SetZeroAddr() public { // create gateway address initialGateway = address(new L1CustomGateway()); @@ -495,13 +534,6 @@ contract L1GatewayRouterTest is GatewayRouterTest { abi.encode(uint8(0xb1)) ); - // retryable params - uint256 maxSubmissionCost = 40000; - uint256 maxGas = 1000000000; - uint256 gasPrice = 3; - uint256 value = maxSubmissionCost + maxGas * gasPrice; - address creditBackAddress = makeAddr("creditBackAddress"); - // register token to gateway vm.prank(token); L1CustomGateway(initialGateway).registerTokenToL2{ value: retryableCost }( From 8e75c9267d32c10fb59ceb03bf098a9f83868177 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 2 May 2023 11:06:13 +0200 Subject: [PATCH 049/163] Test getGateway --- test-foundry/GatewayRouter.t.sol | 22 ++++++++- test-foundry/L1GatewayRouter.t.sol | 73 ++++++++++++++++++++++-------- 2 files changed, 75 insertions(+), 20 deletions(-) diff --git a/test-foundry/GatewayRouter.t.sol b/test-foundry/GatewayRouter.t.sol index 724ed774d3..1cbb18cb70 100644 --- a/test-foundry/GatewayRouter.t.sol +++ b/test-foundry/GatewayRouter.t.sol @@ -3,5 +3,25 @@ pragma solidity ^0.8.0; import "forge-std/Test.sol"; +import { GatewayRouter } from "contracts/tokenbridge/libraries/gateway/GatewayRouter.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -abstract contract GatewayRouterTest is Test {} +import "forge-std/console.sol"; + +abstract contract GatewayRouterTest is Test { + GatewayRouter public router; + address public defaultGateway; + + // retryable params + uint256 public maxSubmissionCost = 50000; + uint256 public maxGas = 1000000000; + uint256 public gasPriceBid = 3; + uint256 public retryableCost = maxSubmissionCost + maxGas * gasPriceBid; + address public creditBackAddress = makeAddr("creditBackAddress"); + + /* solhint-disable func-name-mixedcase */ + function test_getGateway_DefaultGateway(address token) public { + address gateway = router.getGateway(token); + assertEq(gateway, defaultGateway, "Invalid gateway"); + } +} diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 18478a8970..9dccff4d0a 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -17,25 +17,18 @@ contract L1GatewayRouterTest is GatewayRouterTest { address public owner = makeAddr("owner"); address public user = makeAddr("user"); - address public defaultGateway; address public counterpartGateway = makeAddr("counterpartGateway"); address public inbox; - // retryable params - uint256 public maxSubmissionCost = 50000; - uint256 public maxGas = 1000000000; - uint256 public gasPriceBid = 3; - uint256 public retryableCost = maxSubmissionCost + maxGas * gasPriceBid; - address public creditBackAddress = makeAddr("creditBackAddress"); - function setUp() public { inbox = address(new InboxMock()); - l1Router = new L1GatewayRouter(); - l1Router.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); - defaultGateway = address(new L1ERC20Gateway()); + router = new L1GatewayRouter(); + l1Router = L1GatewayRouter(address(router)); + l1Router.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); + vm.deal(owner, 100 ether); vm.deal(user, 100 ether); } @@ -73,6 +66,48 @@ contract L1GatewayRouterTest is GatewayRouterTest { l1Router.postUpgradeInit(); } + function test_getGateway_DisabledGateway() public { + address token = makeAddr("some token"); + + address[] memory tokens = new address[](1); + tokens[0] = token; + address[] memory gateways = new address[](1); + gateways[0] = address(1); + + vm.prank(owner); + l1Router.setGateways{ value: retryableCost }( + tokens, + gateways, + maxGas, + gasPriceBid, + maxSubmissionCost + ); + + address gateway = router.getGateway(token); + assertEq(gateway, address(0), "Invalid gateway"); + } + + function test_getGateway_CustomGateway(address token) public { + address token = makeAddr("some token"); + + address[] memory tokens = new address[](1); + tokens[0] = token; + address[] memory gateways = new address[](1); + gateways[0] = address(new L1ERC20Gateway()); + + vm.prank(owner); + l1Router.setGateways{ value: retryableCost }( + tokens, + gateways, + maxGas, + gasPriceBid, + maxSubmissionCost + ); + + address gateway = router.getGateway(token); + assertEq(gateway, gateways[0], "Invalid gateway"); + } + function test_setDefaultGateway() public { L1ERC20Gateway newL1DefaultGateway = new L1ERC20Gateway(); address newDefaultGatewayCounterpart = makeAddr("newDefaultGatewayCounterpart"); @@ -183,11 +218,11 @@ contract L1GatewayRouterTest is GatewayRouterTest { // register token to gateway vm.prank(address(customToken)); - customGateway.registerTokenToL2{ value: 4000040000 }( + customGateway.registerTokenToL2{ value: retryableCost }( makeAddr("tokenL2Address"), - 1000000000, - 3, - 40000, + maxGas, + gasPriceBid, + maxSubmissionCost, makeAddr("creditBackAddress") ); @@ -445,11 +480,11 @@ contract L1GatewayRouterTest is GatewayRouterTest { // register tokens to gateways vm.deal(tokens[i], 100 ether); vm.prank(tokens[i]); - L1CustomGateway(gateways[i]).registerTokenToL2{ value: 4000040000 }( + L1CustomGateway(gateways[i]).registerTokenToL2{ value: retryableCost }( makeAddr("tokenL2Address"), - 1000000000, - 3, - 40000, + maxGas, + gasPriceBid, + maxSubmissionCost, makeAddr("creditBackAddress") ); } From be2975eb24e3c524642dfd4653df7c59e28892a6 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 2 May 2023 18:11:58 +0200 Subject: [PATCH 050/163] Implement L1OrbitGatewayRouter and its test cases --- .../ethereum/gateway/L1GatewayRouter.sol | 73 +++- .../ethereum/gateway/L1OrbitGatewayRouter.sol | 155 +++++++ test-foundry/GatewayRouter.t.sol | 11 +- test-foundry/L1GatewayRouter.t.sol | 64 +-- test-foundry/L1OrbitGatewayRouter.t.sol | 398 ++++++++++++++++++ 5 files changed, 657 insertions(+), 44 deletions(-) create mode 100644 contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol create mode 100644 test-foundry/L1OrbitGatewayRouter.t.sol diff --git a/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol b/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol index b625d9925d..724379c7d0 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol @@ -65,7 +65,24 @@ contract L1GatewayRouter is uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost - ) external payable onlyOwner returns (uint256) { + ) external payable virtual onlyOwner returns (uint256) { + return + _setDefaultGateway( + newL1DefaultGateway, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + msg.value + ); + } + + function _setDefaultGateway( + address newL1DefaultGateway, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256 feeAmount + ) internal returns (uint256) { defaultGateway = newL1DefaultGateway; emit DefaultGatewayUpdated(newL1DefaultGateway); @@ -86,7 +103,7 @@ contract L1GatewayRouter is inbox, counterpartGateway, msg.sender, - msg.value, + feeAmount, 0, L2GasParams({ _maxSubmissionCost: _maxSubmissionCost, @@ -109,7 +126,8 @@ contract L1GatewayRouter is uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, - address _creditBackAddress + address _creditBackAddress, + uint256 feeAmount ) internal returns (uint256) { require(_token.length == _gateway.length, "WRONG_LENGTH"); @@ -140,7 +158,7 @@ contract L1GatewayRouter is inbox, counterpartGateway, _creditBackAddress, - msg.value, + feeAmount, 0, L2GasParams({ _maxSubmissionCost: _maxSubmissionCost, @@ -164,7 +182,7 @@ contract L1GatewayRouter is uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost - ) external payable override returns (uint256) { + ) external payable virtual override returns (uint256) { return setGateway(_gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender); } @@ -183,7 +201,26 @@ contract L1GatewayRouter is uint256 _gasPriceBid, uint256 _maxSubmissionCost, address _creditBackAddress - ) public payable override returns (uint256) { + ) public payable virtual override returns (uint256) { + return + _setGatewayWithCreditBack( + _gateway, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + _creditBackAddress, + msg.value + ); + } + + function _setGatewayWithCreditBack( + address _gateway, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + address _creditBackAddress, + uint256 feeAmount + ) internal returns (uint256) { require( ArbitrumEnabledToken(msg.sender).isArbitrumEnabled() == uint8(0xb1), "NOT_ARB_ENABLED" @@ -210,7 +247,8 @@ contract L1GatewayRouter is _maxGas, _gasPriceBid, _maxSubmissionCost, - _creditBackAddress + _creditBackAddress, + feeAmount ); } @@ -220,11 +258,19 @@ contract L1GatewayRouter is uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost - ) external payable onlyOwner returns (uint256) { + ) external payable virtual onlyOwner returns (uint256) { // it is assumed that token and gateway are both contracts // require(_token[i].isContract() && _gateway[i].isContract(), "NOT_CONTRACT"); return - _setGateways(_token, _gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender); + _setGateways( + _token, + _gateway, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + msg.sender, + msg.value + ); } function outboundTransfer( @@ -291,12 +337,9 @@ contract L1GatewayRouter is _; } - function supportsInterface(bytes4 interfaceId) - public - view - override(ERC165, IERC165) - returns (bool) - { + function supportsInterface( + bytes4 interfaceId + ) public view override(ERC165, IERC165) returns (bool) { // registering interfaces that is added after arb-bridge-peripherals >1.0.11 // using function selector instead of single function interfaces to reduce bloat return diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol new file mode 100644 index 0000000000..292bb0505c --- /dev/null +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import { L1GatewayRouter } from "./L1GatewayRouter.sol"; +import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; + +/** + * @title Handles deposits from Ethereum into L2 in ERC20-based rollups where custom token is used to pay for fees. Tokens are routed to their appropriate L1 gateway. + * @notice Router itself also conforms to the Gateway interface. Router also serves as an L1-L2 token address oracle. + */ +contract L1OrbitGatewayRouter is L1GatewayRouter { + function setDefaultGateway( + address newL1DefaultGateway, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256 feeAmount + ) external onlyOwner returns (uint256) { + return + _setDefaultGateway( + newL1DefaultGateway, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + feeAmount + ); + } + + function setGateway( + address _gateway, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + address _creditBackAddress, + uint256 feeAmount + ) public returns (uint256) { + return + _setGatewayWithCreditBack( + _gateway, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + _creditBackAddress, + feeAmount + ); + } + + function setGateway( + address _gateway, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256 feeAmount + ) external returns (uint256) { + return + setGateway(_gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender, feeAmount); + } + + function setGateways( + address[] memory _token, + address[] memory _gateway, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256 feeAmount + ) external payable onlyOwner returns (uint256) { + return + _setGateways( + _token, + _gateway, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + msg.sender, + feeAmount + ); + } + + 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) { + return + IERC20Inbox(_inbox).createRetryableTicket( + _to, + _l2CallValue, + _maxSubmissionCost, + _refundTo, + _user, + _maxGas, + _gasPriceBid, + _totalFeeAmount, + _data + ); + } + + /** + * @notice Revert 'setGateway' entrypoint which doesn't have total amount of token fees as an argument. + */ + function setGateway( + address, + uint256, + uint256, + uint256, + address + ) public payable override returns (uint256) { + revert("NOT_SUPPORTED_IN_ORBIT"); + } + + /** + * @notice Revert 'setDefaultGateway' entrypoint which doesn't have total amount of token fees as an argument. + */ + function setDefaultGateway( + address, + uint256, + uint256, + uint256 + ) external payable override onlyOwner returns (uint256) { + revert("NOT_SUPPORTED_IN_ORBIT"); + } + + /** + * @notice Revert 'setGateway' entrypoint which doesn't have total amount of token fees as an argument. + */ + function setGateway( + address, + uint256, + uint256, + uint256 + ) external payable override returns (uint256) { + revert("NOT_SUPPORTED_IN_ORBIT"); + } + + /** + * @notice Revert 'setGateways' entrypoint which doesn't have total amount of token fees as an argument. + */ + function setGateways( + address[] memory, + address[] memory, + uint256, + uint256, + uint256 + ) external payable override onlyOwner returns (uint256) { + revert("NOT_SUPPORTED_IN_ORBIT"); + } +} diff --git a/test-foundry/GatewayRouter.t.sol b/test-foundry/GatewayRouter.t.sol index 1cbb18cb70..57d5642143 100644 --- a/test-foundry/GatewayRouter.t.sol +++ b/test-foundry/GatewayRouter.t.sol @@ -6,17 +6,15 @@ import "forge-std/Test.sol"; import { GatewayRouter } from "contracts/tokenbridge/libraries/gateway/GatewayRouter.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "forge-std/console.sol"; - abstract contract GatewayRouterTest is Test { GatewayRouter public router; address public defaultGateway; // retryable params - uint256 public maxSubmissionCost = 50000; + uint256 public maxSubmissionCost; uint256 public maxGas = 1000000000; uint256 public gasPriceBid = 3; - uint256 public retryableCost = maxSubmissionCost + maxGas * gasPriceBid; + uint256 public retryableCost; address public creditBackAddress = makeAddr("creditBackAddress"); /* solhint-disable func-name-mixedcase */ @@ -24,4 +22,9 @@ abstract contract GatewayRouterTest is Test { address gateway = router.getGateway(token); assertEq(gateway, defaultGateway, "Invalid gateway"); } + + function test_finalizeInboundTransfer() public { + vm.expectRevert("ONLY_OUTBOUND_ROUTER"); + router.finalizeInboundTransfer(address(1), address(2), address(3), 0, ""); + } } diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 9dccff4d0a..858243e739 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -20,15 +20,17 @@ contract L1GatewayRouterTest is GatewayRouterTest { address public counterpartGateway = makeAddr("counterpartGateway"); address public inbox; - function setUp() public { + function setUp() public virtual { inbox = address(new InboxMock()); - defaultGateway = address(new L1ERC20Gateway()); router = new L1GatewayRouter(); l1Router = L1GatewayRouter(address(router)); l1Router.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); + maxSubmissionCost = 50000; + retryableCost = maxSubmissionCost + maxGas * gasPriceBid; + vm.deal(owner, 100 ether); vm.deal(user, 100 ether); } @@ -66,7 +68,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { l1Router.postUpgradeInit(); } - function test_getGateway_DisabledGateway() public { + function test_getGateway_DisabledGateway() public virtual { address token = makeAddr("some token"); address[] memory tokens = new address[](1); @@ -87,7 +89,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(gateway, address(0), "Invalid gateway"); } - function test_getGateway_CustomGateway(address token) public { + function test_getGateway_CustomGateway() public virtual { address token = makeAddr("some token"); address[] memory tokens = new address[](1); @@ -108,7 +110,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(gateway, gateways[0], "Invalid gateway"); } - function test_setDefaultGateway() public { + function test_setDefaultGateway() public virtual { L1ERC20Gateway newL1DefaultGateway = new L1ERC20Gateway(); address newDefaultGatewayCounterpart = makeAddr("newDefaultGatewayCounterpart"); newL1DefaultGateway.initialize( @@ -160,7 +162,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } - function test_setDefaultGateway_AddressZero() public { + function test_setDefaultGateway_AddressZero() public virtual { address newL1DefaultGateway = address(0); // event checkers @@ -201,7 +203,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } - function test_setGateway() public { + function test_setGateway() public virtual { // create gateway L1CustomGateway customGateway = new L1CustomGateway(); address l2Counterpart = makeAddr("l2Counterpart"); @@ -269,7 +271,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } - function test_setGateway_CustomCreditback() public { + function test_setGateway_CustomCreditback() public virtual { // create gateway L1CustomGateway customGateway = new L1CustomGateway(); address l2Counterpart = makeAddr("l2Counterpart"); @@ -338,7 +340,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } - function test_setGateway_revert_NotArbEnabled() public { + function test_setGateway_revert_NotArbEnabled() public virtual { address nonArbEnabledToken = address(new ERC20("X", "Y")); vm.deal(nonArbEnabledToken, 100 ether); vm.mockCall( @@ -358,7 +360,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } - function test_setGateway_revert_NotToContract() public { + function test_setGateway_revert_NotToContract() public virtual { address token = address(new ERC20("X", "Y")); vm.deal(token, 100 ether); vm.mockCall(token, abi.encodeWithSignature("isArbitrumEnabled()"), abi.encode(uint8(0xb1))); @@ -376,7 +378,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } - function test_setGateway_revert_NoUpdateToDifferentAddress() public { + function test_setGateway_revert_NoUpdateToDifferentAddress() public virtual { // create gateway address initialGateway = address(new L1CustomGateway()); address l2Counterpart = makeAddr("l2Counterpart"); @@ -431,7 +433,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } - function test_setGateway_revert_TokenNotHandledByGateway() public { + function test_setGateway_revert_TokenNotHandledByGateway() public virtual { // create gateway L1CustomGateway gateway = new L1CustomGateway(); @@ -451,7 +453,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } - function test_setGateways() public { + function test_setGateways() public virtual { // create tokens and gateways address[] memory tokens = new address[](2); tokens[0] = address(new ERC20("1", "1")); @@ -530,7 +532,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(seqNum, 0, "Invalid seqNum"); } - function test_setGateways_revert_WrongLength() public { + function test_setGateways_revert_WrongLength() public virtual { address[] memory tokens = new address[](2); tokens[0] = address(new ERC20("1", "1")); tokens[1] = address(new ERC20("2", "2")); @@ -549,7 +551,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } - function test_setGateways_SetZeroAddr() public { + function test_setGateways_SetZeroAddr() public virtual { // create gateway address initialGateway = address(new L1CustomGateway()); address l2Counterpart = makeAddr("l2Counterpart"); @@ -674,7 +676,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(l1Router.supportsInterface(iface), expected, "Interface shouldn't be supported"); } - function test_outboundTransfer() public { + function test_outboundTransfer() public virtual { // init default gateway L1ERC20Gateway(defaultGateway).initialize( makeAddr("defaultGatewayCounterpart"), @@ -686,7 +688,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { // set default gateway vm.prank(owner); - l1Router.setDefaultGateway{ value: retryableCost }( + l1Router.setDefaultGateway{ value: _getValue() }( address(defaultGateway), maxGas, gasPriceBid, @@ -706,8 +708,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { /// deposit data address to = address(401); uint256 amount = 103; - bytes memory callHookData = ""; - bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); + bytes memory userEncodedData = _buildUserEncodedData(""); // expect event vm.expectEmit(true, true, true, true); @@ -715,7 +716,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { /// deposit it vm.prank(user); - l1Router.outboundTransfer{ value: retryableCost }( + l1Router.outboundTransfer{ value: _getValue() }( address(token), to, amount, @@ -736,7 +737,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } - function test_outboundTransferCustomRefund() public { + function test_outboundTransferCustomRefund() public virtual { // init default gateway L1ERC20Gateway(defaultGateway).initialize( makeAddr("defaultGatewayCounterpart"), @@ -748,7 +749,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { // set default gateway vm.prank(owner); - l1Router.setDefaultGateway{ value: retryableCost }( + l1Router.setDefaultGateway{ value: _getValue() }( address(defaultGateway), maxGas, gasPriceBid, @@ -769,8 +770,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { address refundTo = address(400); address to = address(401); uint256 amount = 103; - bytes memory callHookData = ""; - bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); + bytes memory userEncodedData = _buildUserEncodedData(""); // expect event vm.expectEmit(true, true, true, true); @@ -778,7 +778,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { /// deposit it vm.prank(user); - l1Router.outboundTransferCustomRefund{ value: retryableCost }( + l1Router.outboundTransferCustomRefund{ value: _getValue() }( address(token), refundTo, to, @@ -800,6 +800,20 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } + //// + // Helper functions + //// + function _buildUserEncodedData( + bytes memory callHookData + ) internal view virtual returns (bytes memory) { + bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); + return userEncodedData; + } + + function _getValue() internal view virtual returns (uint256) { + return retryableCost; + } + //// // Event declarations //// diff --git a/test-foundry/L1OrbitGatewayRouter.t.sol b/test-foundry/L1OrbitGatewayRouter.t.sol new file mode 100644 index 0000000000..58ddfbf8ab --- /dev/null +++ b/test-foundry/L1OrbitGatewayRouter.t.sol @@ -0,0 +1,398 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import { L1GatewayRouterTest } from "./L1GatewayRouter.t.sol"; +import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; +import { L1OrbitERC20Gateway } from "contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol"; +import { L1OrbitGatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol"; +import { L2GatewayRouter } from "contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol"; +import { L1GatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol"; +import { L1CustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20PresetMinterPauser } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; + +contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { + L1OrbitGatewayRouter public l1OrbitRouter; + uint256 public nativeTokenTotalFee; + + function setUp() public override { + inbox = address(new ERC20InboxMock()); + + defaultGateway = address(new L1OrbitERC20Gateway()); + + router = new L1OrbitGatewayRouter(); + l1Router = L1GatewayRouter(address(router)); + l1OrbitRouter = L1OrbitGatewayRouter(address(router)); + l1OrbitRouter.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); + + maxSubmissionCost = 0; + retryableCost = 0; + nativeTokenTotalFee = gasPriceBid * maxGas; + + vm.deal(owner, 100 ether); + vm.deal(user, 100 ether); + } + + /* solhint-disable func-name-mixedcase */ + function test_getGateway_CustomGateway() public override { + address token = makeAddr("some token"); + + address[] memory tokens = new address[](1); + tokens[0] = token; + address[] memory gateways = new address[](1); + gateways[0] = address(new L1OrbitERC20Gateway()); + + vm.prank(owner); + l1OrbitRouter.setGateways( + tokens, + gateways, + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + address gateway = router.getGateway(token); + assertEq(gateway, gateways[0], "Invalid gateway"); + } + + function test_getGateway_DisabledGateway() public override { + address token = makeAddr("some token"); + + address[] memory tokens = new address[](1); + tokens[0] = token; + address[] memory gateways = new address[](1); + gateways[0] = address(1); + + vm.prank(owner); + l1OrbitRouter.setGateways( + tokens, + gateways, + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + address gateway = router.getGateway(token); + assertEq(gateway, address(0), "Invalid gateway"); + } + + function test_outboundTransfer() public override { + // init default gateway + L1OrbitERC20Gateway(defaultGateway).initialize( + makeAddr("defaultGatewayCounterpart"), + address(l1Router), + inbox, + 0x0000000000000000000000000000000000000000000000000000000000000001, + makeAddr("l2BeaconProxyFactory") + ); + + // set default gateway + vm.prank(owner); + l1OrbitRouter.setDefaultGateway( + address(defaultGateway), + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + // create token + ERC20PresetMinterPauser token = new ERC20PresetMinterPauser("X", "Y"); + token.mint(user, 10000); + vm.prank(user); + token.approve(defaultGateway, 103); + + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(defaultGateway)); + + /// deposit data + address to = address(401); + uint256 amount = 103; + bytes memory userEncodedData = _buildUserEncodedData(""); + + // expect event + vm.expectEmit(true, true, true, true); + emit TransferRouted(address(token), user, to, address(defaultGateway)); + + /// deposit it + vm.prank(user); + l1Router.outboundTransfer{ value: _getValue() }( + address(token), + to, + amount, + maxGas, + gasPriceBid, + userEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, amount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(defaultGateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + amount, + "Wrong defaultGateway balance" + ); + } + + function test_outboundTransferCustomRefund() public override { + // init default gateway + L1OrbitERC20Gateway(defaultGateway).initialize( + makeAddr("defaultGatewayCounterpart"), + address(l1Router), + inbox, + 0x0000000000000000000000000000000000000000000000000000000000000001, + makeAddr("l2BeaconProxyFactory") + ); + + // set default gateway + vm.prank(owner); + l1OrbitRouter.setDefaultGateway( + address(defaultGateway), + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + // create token + ERC20PresetMinterPauser token = new ERC20PresetMinterPauser("X", "Y"); + token.mint(user, 10000); + vm.prank(user); + token.approve(defaultGateway, 103); + + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(defaultGateway)); + + /// deposit data + address refundTo = address(400); + address to = address(401); + uint256 amount = 103; + bytes memory userEncodedData = _buildUserEncodedData(""); + + // expect event + vm.expectEmit(true, true, true, true); + emit TransferRouted(address(token), user, to, address(defaultGateway)); + + /// deposit it + vm.prank(user); + l1Router.outboundTransferCustomRefund{ value: _getValue() }( + address(token), + refundTo, + to, + amount, + maxGas, + gasPriceBid, + userEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, amount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(defaultGateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + amount, + "Wrong defaultGateway balance" + ); + } + + function test_setDefaultGateway() public override { + L1OrbitERC20Gateway newL1DefaultGateway = new L1OrbitERC20Gateway(); + address newDefaultGatewayCounterpart = makeAddr("newDefaultGatewayCounterpart"); + newL1DefaultGateway.initialize( + newDefaultGatewayCounterpart, + address(l1OrbitRouter), + inbox, + 0x0000000000000000000000000000000000000000000000000000000000000001, + makeAddr("l2BeaconProxyFactory") + ); + + // event checkers + vm.expectEmit(true, true, true, true); + emit DefaultGatewayUpdated(address(newL1DefaultGateway)); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1OrbitRouter), + counterpartGateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + abi.encodeWithSelector( + L2GatewayRouter.setDefaultGateway.selector, + newDefaultGatewayCounterpart + ) + ); + + // set it + vm.prank(owner); + uint256 seqNum = l1OrbitRouter.setDefaultGateway( + address(newL1DefaultGateway), + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + /// checks + assertEq( + l1OrbitRouter.defaultGateway(), + address(newL1DefaultGateway), + "Invalid newL1DefaultGateway" + ); + + assertEq(seqNum, 0, "Invalid seqNum"); + } + + function test_setDefaultGateway_AddressZero() public override { + address newL1DefaultGateway = address(0); + + // event checkers + vm.expectEmit(true, true, true, true); + emit DefaultGatewayUpdated(address(newL1DefaultGateway)); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1OrbitRouter), + counterpartGateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + abi.encodeWithSelector(L2GatewayRouter.setDefaultGateway.selector, address(0)) + ); + + // set it + vm.prank(owner); + uint256 seqNum = l1OrbitRouter.setDefaultGateway( + newL1DefaultGateway, + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + /// checks + assertEq( + l1OrbitRouter.defaultGateway(), + address(newL1DefaultGateway), + "Invalid newL1DefaultGateway" + ); + + assertEq(seqNum, 0, "Invalid seqNum"); + } + + function test_setDefaultGateway_revert_NotSupportedInOrbit() public { + vm.prank(owner); + vm.expectRevert("NOT_SUPPORTED_IN_ORBIT"); + l1OrbitRouter.setDefaultGateway{ value: retryableCost }( + address(5), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + + function test_setGateway() public override { + // TODO after custom gateway changes + } + + function test_setGateway_CustomCreditback() public override { + // TODO after custom gateway changes + } + + function test_setGateway_revert_NoUpdateToDifferentAddress() public override { + // TODO after custom gateway changes + } + + function test_setGateway_revert_NotArbEnabled() public override { + address nonArbEnabledToken = address(new ERC20("X", "Y")); + vm.deal(nonArbEnabledToken, 100 ether); + vm.mockCall( + nonArbEnabledToken, + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb2)) + ); + + vm.prank(nonArbEnabledToken); + vm.expectRevert("NOT_ARB_ENABLED"); + l1OrbitRouter.setGateway( + makeAddr("gateway"), + 100000, + 3, + 200, + makeAddr("creditback"), + nativeTokenTotalFee + ); + } + + function test_setGateway_revert_NotToContract() public override { + // TODO after custom gateway changes + } + + function test_setGateway_revert_TokenNotHandledByGateway() public override { + // TODO after custom gateway changes + } + + function test_setGateways() public override { + // TODO after custom gateway changes + } + + function test_setGateways_SetZeroAddr() public override { + // TODO after custom gateway changes + } + + function test_setGateways_revert_WrongLength() public override { + // TODO after custom gateway changes + } + + //// + // Helper functions + //// + function _buildUserEncodedData( + bytes memory callHookData + ) internal view override returns (bytes memory) { + bytes memory userEncodedData = abi.encode( + maxSubmissionCost, + callHookData, + nativeTokenTotalFee + ); + return userEncodedData; + } + + function _getValue() internal pure override returns (uint256) { + return 0; + } + + event ERC20InboxRetryableTicket( + address from, + address to, + uint256 l2CallValue, + uint256 maxGas, + uint256 gasPrice, + uint256 tokenTotalFeeAmount, + bytes data + ); +} From d78c56a7c50f2f5840ba99ca073cfbefc7e78007 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 3 May 2023 11:21:38 +0200 Subject: [PATCH 051/163] Add L1OrbitCustomGateway implementation --- .../ethereum/gateway/L1CustomGateway.sol | 45 ++++-- .../ethereum/gateway/L1OrbitCustomGateway.sol | 141 ++++++++++++++++++ .../ethereum/gateway/L1OrbitERC20Gateway.sol | 2 +- 3 files changed, 176 insertions(+), 12 deletions(-) create mode 100644 contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol diff --git a/contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol index ea06568091..a86244a267 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol @@ -113,7 +113,9 @@ contract L1CustomGateway is L1ArbitrumExtendedGateway, ICustomGateway { * @param l1ERC20 address of L1 token * @return L2 address of a bridged ERC20 token */ - function calculateL2TokenAddress(address l1ERC20) public view override(ITokenGateway, TokenGateway) returns (address) { + function calculateL2TokenAddress( + address l1ERC20 + ) public view override(ITokenGateway, TokenGateway) returns (address) { return l1ToL2Token[l1ERC20]; } @@ -130,7 +132,7 @@ contract L1CustomGateway is L1ArbitrumExtendedGateway, ICustomGateway { uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost - ) external payable returns (uint256) { + ) external payable virtual returns (uint256) { return registerTokenToL2(_l2Address, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender); } @@ -150,15 +152,36 @@ contract L1CustomGateway is L1ArbitrumExtendedGateway, ICustomGateway { uint256 _maxSubmissionCost, address _creditBackAddress ) public payable virtual returns (uint256) { - require( - ArbitrumEnabledToken(msg.sender).isArbitrumEnabled() == uint8(0xb1), - "NOT_ARB_ENABLED" - ); + return + _registerTokenToL2( + _l2Address, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + _creditBackAddress, + msg.value + ); + } - address currL2Addr = l1ToL2Token[msg.sender]; - if (currL2Addr != address(0)) { - // if token is already set, don't allow it to set a different L2 address - require(currL2Addr == _l2Address, "NO_UPDATE_TO_DIFFERENT_ADDR"); + function _registerTokenToL2( + address _l2Address, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + address _creditBackAddress, + uint256 _feeAmount + ) internal returns (uint256) { + { + require( + ArbitrumEnabledToken(msg.sender).isArbitrumEnabled() == uint8(0xb1), + "NOT_ARB_ENABLED" + ); + + address currL2Addr = l1ToL2Token[msg.sender]; + if (currL2Addr != address(0)) { + // if token is already set, don't allow it to set a different L2 address + require(currL2Addr == _l2Address, "NO_UPDATE_TO_DIFFERENT_ADDR"); + } } l1ToL2Token[msg.sender] = _l2Address; @@ -181,7 +204,7 @@ contract L1CustomGateway is L1ArbitrumExtendedGateway, ICustomGateway { inbox, counterpartGateway, _creditBackAddress, - msg.value, + _feeAmount, 0, _maxSubmissionCost, _maxGas, diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol new file mode 100644 index 0000000000..795f54c07e --- /dev/null +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import { L1CustomGateway } from "./L1CustomGateway.sol"; +import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; + +/** + * @title Gateway for "custom" bridging functionality in an ERC20-based rollup. + * @notice Adds new entrypoints that have `_feeAmount` as parameter, while entrypoints without that parameter are reverted. + */ +contract L1OrbitCustomGateway is L1CustomGateway { + function registerTokenToL2( + address _l2Address, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256 _feeAmount + ) external returns (uint256) { + return + registerTokenToL2( + _l2Address, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + msg.sender, + _feeAmount + ); + } + + function registerTokenToL2( + address _l2Address, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + address _creditBackAddress, + uint256 _feeAmount + ) public returns (uint256) { + return + _registerTokenToL2( + _l2Address, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + _creditBackAddress, + _feeAmount + ); + } + + /** + * @notice Revert 'registerTokenToL2' entrypoint which doesn't have total amount of token fees as an argument. + */ + function registerTokenToL2( + address, + uint256, + uint256, + uint256, + address + ) public payable override returns (uint256) { + revert("NOT_SUPPORTED_IN_ORBIT"); + } + + /** + * @notice Revert 'registerTokenToL2' entrypoint which doesn't have total amount of token fees as an argument. + */ + function registerTokenToL2( + address, + uint256, + uint256, + uint256 + ) external payable override returns (uint256) { + revert("NOT_SUPPORTED_IN_ORBIT"); + } + + 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, + 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) { + return + IERC20Inbox(_inbox).createRetryableTicket( + _to, + _l2CallValue, + _maxSubmissionCost, + _refundTo, + _user, + _maxGas, + _gasPriceBid, + _totalFeeAmount, + _data + ); + } +} diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index 7a8ff0fd06..0a94ed6392 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import "./L1ERC20Gateway.sol"; +import { L1ERC20Gateway, IERC20 } from "./L1ERC20Gateway.sol"; import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; /** From 982518a5c778ea66801b0f642804a8f6264afbe5 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 4 May 2023 10:31:54 +0200 Subject: [PATCH 052/163] Implement test cases for L1CustomGateway --- .../ethereum/gateway/L1CustomGateway.sol | 23 +- .../ethereum/gateway/L1OrbitCustomGateway.sol | 32 ++ test-foundry/L1ArbitrumExtendedGateway.t.sol | 140 ++++- test-foundry/L1CustomGateway.t.sol | 525 ++++++++++++++++++ test-foundry/L1ERC20Gateway.t.sol | 164 +----- test-foundry/L1OrbitERC20Gateway.t.sol | 1 - 6 files changed, 727 insertions(+), 158 deletions(-) create mode 100644 test-foundry/L1CustomGateway.t.sol diff --git a/contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol index a86244a267..0f4ec483cb 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol @@ -234,7 +234,26 @@ contract L1CustomGateway is L1ArbitrumExtendedGateway, ICustomGateway { uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost - ) external payable onlyOwner returns (uint256) { + ) external payable virtual onlyOwner returns (uint256) { + return + _forceRegisterTokenToL2( + _l1Addresses, + _l2Addresses, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + msg.value + ); + } + + function _forceRegisterTokenToL2( + address[] calldata _l1Addresses, + address[] calldata _l2Addresses, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256 _feeAmount + ) internal returns (uint256) { require(_l1Addresses.length == _l2Addresses.length, "INVALID_LENGTHS"); for (uint256 i = 0; i < _l1Addresses.length; i++) { @@ -255,7 +274,7 @@ contract L1CustomGateway is L1ArbitrumExtendedGateway, ICustomGateway { inbox, counterpartGateway, msg.sender, - msg.value, + _feeAmount, 0, _maxSubmissionCost, _maxGas, diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol index 795f54c07e..a71b8088b1 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol @@ -47,6 +47,25 @@ contract L1OrbitCustomGateway is L1CustomGateway { ); } + function forceRegisterTokenToL2( + address[] calldata _l1Addresses, + address[] calldata _l2Addresses, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256 _feeAmount + ) external payable virtual onlyOwner returns (uint256) { + return + _forceRegisterTokenToL2( + _l1Addresses, + _l2Addresses, + _maxGas, + _gasPriceBid, + _maxSubmissionCost, + _feeAmount + ); + } + /** * @notice Revert 'registerTokenToL2' entrypoint which doesn't have total amount of token fees as an argument. */ @@ -72,6 +91,19 @@ contract L1OrbitCustomGateway is L1CustomGateway { revert("NOT_SUPPORTED_IN_ORBIT"); } + /** + * @notice Revert 'forceRegisterTokenToL2' entrypoint which doesn't have total amount of token fees as an argument. + */ + function forceRegisterTokenToL2( + address[] calldata, + address[] calldata, + uint256, + uint256, + uint256 + ) external payable override onlyOwner returns (uint256) { + revert("NOT_SUPPORTED_IN_ORBIT"); + } + function _parseUserEncodedData( bytes memory data ) diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol index 3007fb6377..10f44f6df9 100644 --- a/test-foundry/L1ArbitrumExtendedGateway.t.sol +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -4,10 +4,26 @@ pragma solidity ^0.8.0; import "forge-std/Test.sol"; import "contracts/tokenbridge/ethereum/gateway/L1ArbitrumExtendedGateway.sol"; +import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; +import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; abstract contract L1ArbitrumExtendedGatewayTest is Test { IL1ArbitrumGateway public l1Gateway; + IERC20 public token; + address public l2Gateway = makeAddr("l2Gateway"); + address public router = makeAddr("router"); + address public inbox; + address public user = makeAddr("user"); + + // retryable params + uint256 public maxSubmissionCost; + uint256 public maxGas = 1000000000; + uint256 public gasPriceBid = 3; + uint256 public retryableCost; + address public creditBackAddress = makeAddr("creditBackAddress"); + + /* solhint-disable func-name-mixedcase */ function test_encodeWithdrawal(uint256 exitNum, address dest) public { bytes32 encodedWithdrawal = L1ArbitrumExtendedGateway(address(l1Gateway)).encodeWithdrawal( exitNum, @@ -18,6 +34,57 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { assertEq(encodedWithdrawal, expectedEncoding, "Invalid encodeWithdrawal"); } + function test_finalizeInboundTransfer() public { + // fund gateway with tokens being withdrawn + vm.prank(address(l1Gateway)); + TestERC20(address(token)).mint(); + + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + // withdrawal params + address from = address(3000); + uint256 withdrawalAmount = 25; + 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(address(token), from, user, withdrawalAmount, data); + + // check tokens are properly released + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceAfter - userBalanceBefore, withdrawalAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceBefore - l1GatewayBalanceAfter, + withdrawalAmount, + "Wrong l1 gateway balance" + ); + } + + function test_finalizeInboundTransfer_revert_NotFromBridge() public { + address notBridge = address(300); + vm.prank(notBridge); + vm.expectRevert("NOT_FROM_BRIDGE"); + l1Gateway.finalizeInboundTransfer(address(token), user, user, 100, ""); + } + + function test_finalizeInboundTransfer_revert_OnlyCounterpartGateway() public { + address notCounterPartGateway = address(400); + InboxMock(address(inbox)).setL2ToL1Sender(notCounterPartGateway); + + // trigger withdrawal + vm.prank(address(IInbox(l1Gateway.inbox()).bridge())); + vm.expectRevert("ONLY_COUNTERPART_GATEWAY"); + l1Gateway.finalizeInboundTransfer(address(token), user, user, 100, ""); + } + function test_getExternalCall(uint256 exitNum, address dest, bytes memory data) public { (address target, bytes memory extData) = L1ArbitrumExtendedGateway(address(l1Gateway)) .getExternalCall(exitNum, dest, data); @@ -37,8 +104,7 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { function test_getExternalCall_Redirected( uint256 exitNum, address initialDest, - address newDest, - bytes memory data + address newDest ) public { // redirect vm.prank(initialDest); @@ -66,6 +132,64 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { assertEq(newData.length, 0, "Invalid _newData"); } + function test_outboundTransferCustomRefund_revert_ExtraDataDisabled() public { + bytes memory callHookData = abi.encodeWithSignature("doSomething()"); + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + vm.prank(router); + vm.expectRevert("EXTRA_DATA_DISABLED"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(token), + user, + user, + 400, + 0.1 ether, + 0.01 ether, + routerEncodedData + ); + } + + function test_outboundTransferCustomRefund_revert_L1NotContract() public { + address invalidTokenAddress = address(70); + + vm.prank(router); + vm.expectRevert("L1_NOT_CONTRACT"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(invalidTokenAddress), + user, + user, + 400, + 0.1 ether, + 0.01 ether, + buildRouterEncodedData("") + ); + } + + function test_outboundTransferCustomRefund_revert_NotFromRouter() public { + vm.expectRevert("NOT_FROM_ROUTER"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(token), + user, + user, + 400, + 0.1 ether, + 0.01 ether, + "" + ); + } + + function test_supportsInterface(bytes4 iface) public { + bool expected = false; + if ( + iface == type(IERC165).interfaceId || + iface == IL1ArbitrumGateway.outboundTransferCustomRefund.selector + ) { + expected = true; + } + + assertEq(l1Gateway.supportsInterface(iface), expected, "Interface shouldn't be supported"); + } + function test_transferExitAndCall_EmptyData_NotRedirected( uint256 exitNum, address initialDestination, @@ -295,6 +419,18 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { ); } + //// + // Helper functions + //// + function buildRouterEncodedData( + bytes memory callHookData + ) internal view virtual returns (bytes memory) { + bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); + bytes memory routerEncodedData = abi.encode(user, userEncodedData); + + return routerEncodedData; + } + ///// /// Event declarations ///// diff --git a/test-foundry/L1CustomGateway.t.sol b/test-foundry/L1CustomGateway.t.sol new file mode 100644 index 0000000000..2f3d13cc2d --- /dev/null +++ b/test-foundry/L1CustomGateway.t.sol @@ -0,0 +1,525 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import { L1ArbitrumExtendedGatewayTest } from "./L1ArbitrumExtendedGateway.t.sol"; +import { L1CustomGateway, IInbox, ITokenGateway, IERC165, IL1ArbitrumGateway } from "contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol"; +import { L2CustomGateway } from "contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol"; +import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; +import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { + // gateway params + address public owner = makeAddr("owner"); + + function setUp() public virtual { + inbox = address(new InboxMock()); + + l1Gateway = new L1CustomGateway(); + L1CustomGateway(address(l1Gateway)).initialize(l2Gateway, router, inbox, owner); + + token = IERC20(address(new TestERC20())); + + maxSubmissionCost = 20; + retryableCost = maxSubmissionCost + gasPriceBid * maxGas; + + // fund user and router + vm.prank(user); + TestERC20(address(token)).mint(); + vm.deal(router, 100 ether); + vm.deal(address(token), 100 ether); + vm.deal(owner, 100 ether); + } + + /* solhint-disable func-name-mixedcase */ + function test_calculateL2TokenAddress(address l1Token, address l2Token) public { + vm.deal(l1Token, 100 ether); + + // register token to gateway + vm.mockCall( + address(l1Token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(l1Token)); + L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + l2Token, + maxGas, + gasPriceBid, + maxSubmissionCost, + makeAddr("creditBackAddress") + ); + + assertEq(l1Gateway.calculateL2TokenAddress(l1Token), l2Token, "Invalid L2 token address"); + } + + function test_initialize() public virtual { + L1CustomGateway gateway = new L1CustomGateway(); + gateway.initialize(l2Gateway, router, inbox, owner); + + assertEq(gateway.counterpartGateway(), l2Gateway, "Invalid counterpartGateway"); + assertEq(gateway.router(), router, "Invalid router"); + assertEq(gateway.inbox(), inbox, "Invalid inbox"); + assertEq(gateway.owner(), owner, "Invalid owner"); + assertEq(gateway.whitelist(), address(0), "Invalid whitelist"); + } + + function test_outboundTransfer() public virtual { + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + uint256 depositAmount = 300; + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(token)); + L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + makeAddr("creditBackAddress") + ); + + // approve token + vm.prank(user); + token.approve(address(l1Gateway), depositAmount); + + // 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(address(token), user, user, depositAmount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(token), user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + l1Gateway.outboundTransfer{ value: retryableCost }( + address(token), + user, + depositAmount, + maxGas, + gasPriceBid, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + } + + function test_outboundTransferCustomRefund() public virtual { + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + uint256 depositAmount = 450; + address refundTo = address(2000); + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(token)); + L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + makeAddr("creditBackAddress") + ); + + // approve token + vm.prank(user); + token.approve(address(l1Gateway), depositAmount); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(refundTo, user); + + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + l1Gateway.getOutboundCalldata(address(token), user, user, depositAmount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(token), user, user, 0, depositAmount); + + // trigger deposit + vm.prank(router); + l1Gateway.outboundTransferCustomRefund{ value: retryableCost }( + address(token), + refundTo, + user, + depositAmount, + maxGas, + gasPriceBid, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + } + + function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public { + uint256 tooManyTokens = 500 ether; + + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(token)); + L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + makeAddr("creditBackAddress") + ); + + vm.prank(router); + vm.expectRevert("ERC20: insufficient allowance"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(token), + user, + user, + tooManyTokens, + 0.1 ether, + 0.01 ether, + buildRouterEncodedData("") + ); + } + + function test_forceRegisterTokenToL2() public { + address[] memory l1Tokens = new address[](2); + l1Tokens[0] = makeAddr("l1Token1"); + l1Tokens[1] = makeAddr("l1Token2"); + address[] memory l2Tokens = new address[](2); + l2Tokens[0] = makeAddr("l2Token1"); + l2Tokens[1] = makeAddr("l2Token2"); + + // expect events + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Tokens[0], l2Tokens[0]); + + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Tokens[1], l2Tokens[1]); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + abi.encodeWithSelector(L2CustomGateway.registerTokenFromL1.selector, l1Tokens, l2Tokens) + ); + + // register token to gateway + vm.prank(owner); + uint256 seqNum = L1CustomGateway(address(l1Gateway)).forceRegisterTokenToL2{ + value: retryableCost + }(l1Tokens, l2Tokens, maxGas, gasPriceBid, maxSubmissionCost); + + ///// checks + assertEq( + L1CustomGateway(address(l1Gateway)).l1ToL2Token(l1Tokens[0]), + l2Tokens[0], + "Invalid L2 token" + ); + + assertEq( + L1CustomGateway(address(l1Gateway)).l1ToL2Token(l1Tokens[1]), + l2Tokens[1], + "Invalid L2 token" + ); + + assertEq(seqNum, 0, "Invalid seqNum"); + } + + function test_forceRegisterTokenToL2_revert_InvalidLength() public { + vm.prank(owner); + vm.expectRevert("INVALID_LENGTHS"); + L1CustomGateway(address(l1Gateway)).forceRegisterTokenToL2{ value: retryableCost }( + new address[](1), + new address[](2), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + + function test_forceRegisterTokenToL2_revert_OnlyOwner() public { + vm.expectRevert("ONLY_OWNER"); + L1CustomGateway(address(l1Gateway)).forceRegisterTokenToL2{ value: retryableCost }( + new address[](1), + new address[](1), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + + function test_getOutboundCalldata() public { + bytes memory outboundCalldata = l1Gateway.getOutboundCalldata({ + _token: address(token), + _from: user, + _to: address(800), + _amount: 355, + _data: abi.encode("doStuff()") + }); + + bytes memory expectedCalldata = abi.encodeWithSelector( + ITokenGateway.finalizeInboundTransfer.selector, + address(token), + user, + address(800), + 355, + abi.encode("", abi.encode("doStuff()")) + ); + + assertEq(outboundCalldata, expectedCalldata, "Invalid outboundCalldata"); + } + + function test_registerTokenToL2(address l1Token, address l2Token) public { + vm.deal(l1Token, 100 ether); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Token, l2Token); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(l1Token, l1Token); + + address[] memory l1Tokens = new address[](1); + l1Tokens[0] = address(l1Token); + address[] memory l2Tokens = new address[](1); + l2Tokens[0] = address(l2Token); + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + abi.encodeWithSelector(L2CustomGateway.registerTokenFromL1.selector, l1Tokens, l2Tokens) + ); + + // register token to gateway + vm.mockCall( + address(l1Token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(l1Token)); + L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + l2Token, + maxGas, + gasPriceBid, + maxSubmissionCost + ); + + assertEq( + L1CustomGateway(address(l1Gateway)).l1ToL2Token(l1Token), + l2Token, + "Invalid L2 token" + ); + } + + function test_registerTokenToL2_CustomRefund(address l1Token, address l2Token) public { + vm.deal(l1Token, 100 ether); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Token, l2Token); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(creditBackAddress, creditBackAddress); + + address[] memory l1Tokens = new address[](1); + l1Tokens[0] = address(l1Token); + address[] memory l2Tokens = new address[](1); + l2Tokens[0] = address(l2Token); + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + abi.encodeWithSelector(L2CustomGateway.registerTokenFromL1.selector, l1Tokens, l2Tokens) + ); + + // register token to gateway + vm.mockCall( + address(l1Token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(l1Token)); + L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + l2Token, + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress + ); + + assertEq( + L1CustomGateway(address(l1Gateway)).l1ToL2Token(l1Token), + l2Token, + "Invalid L2 token" + ); + } + + function test_registerTokenToL2_revert_NotArbEnabled() public { + // wrong answer + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xdd)) + ); + + vm.prank(address(token)); + vm.expectRevert("NOT_ARB_ENABLED"); + L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + address(102), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress + ); + } + + function test_registerTokenToL2_revert_NoUpdateToDifferentAddress() public { + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + + // set initial address + address initialL2TokenAddress = makeAddr("initial"); + vm.prank(address(token)); + L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + initialL2TokenAddress, + maxGas, + gasPriceBid, + maxSubmissionCost + ); + assertEq( + L1CustomGateway(address(l1Gateway)).l1ToL2Token(address(token)), + initialL2TokenAddress + ); + + // try to set different one + address differentL2TokenAddress = makeAddr("different"); + vm.prank(address(token)); + vm.expectRevert("NO_UPDATE_TO_DIFFERENT_ADDR"); + L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + differentL2TokenAddress, + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + + function test_setOwner(address newOwner) public { + vm.assume(newOwner != address(0)); + + vm.prank(owner); + L1CustomGateway(address(l1Gateway)).setOwner(newOwner); + + assertEq(L1CustomGateway(address(l1Gateway)).owner(), newOwner, "Invalid owner"); + } + + function test_setOwner_revert_InvalidOwner() public { + address invalidOwner = address(0); + + vm.prank(owner); + vm.expectRevert("INVALID_OWNER"); + L1CustomGateway(address(l1Gateway)).setOwner(invalidOwner); + } + + function test_setOwner_revert_OnlyOwner() public { + address nonOwner = address(250); + + vm.prank(nonOwner); + vm.expectRevert("ONLY_OWNER"); + L1CustomGateway(address(l1Gateway)).setOwner(address(300)); + } + + //// + // Event declarations + //// + event TokenSet(address indexed l1Address, address indexed l2Address); + + event DepositInitiated( + address l1Token, + address indexed _from, + address indexed _to, + uint256 indexed _sequenceNumber, + uint256 _amount + ); + event TicketData(uint256 maxSubmissionCost); + event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); + event InboxRetryableTicket(address from, address to, uint256 value, uint256 maxGas, bytes data); +} diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 6fd4ec1f6d..9f9918137b 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -2,25 +2,16 @@ pragma solidity ^0.8.0; -import { L1ArbitrumExtendedGatewayTest } from "./L1ArbitrumExtendedGateway.t.sol"; +import { L1ArbitrumExtendedGatewayTest, InboxMock, TestERC20 } from "./L1ArbitrumExtendedGateway.t.sol"; import "contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol"; -import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; -import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { - IERC20 public token; - // gateway params - address public l2Gateway = address(1000); - address public router = address(1001); - address public inbox; - address public l2BeaconProxyFactory = address(1003); + address public l2BeaconProxyFactory = makeAddr("l2BeaconProxyFactory"); bytes32 public cloneableProxyHash = 0x0000000000000000000000000000000000000000000000000000000000000001; - address public user = address(1004); - function setUp() public virtual { inbox = address(new InboxMock()); @@ -35,6 +26,9 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { token = IERC20(address(new TestERC20())); + maxSubmissionCost = 70; + retryableCost = maxSubmissionCost + gasPriceBid * maxGas; + // fund user and router vm.prank(user); TestERC20(address(token)).mint(); @@ -75,13 +69,9 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); // retryable params - uint256 maxSubmissionCost = 1; - uint256 maxGas = 1000000000; - uint256 gasPrice = 3; uint256 depositAmount = 300; bytes memory callHookData = ""; - bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); - bytes memory routerEncodedData = abi.encode(user, userEncodedData); + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); // approve token vm.prank(user); @@ -108,12 +98,12 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { // trigger deposit vm.prank(router); - l1Gateway.outboundTransfer{ value: maxSubmissionCost + maxGas * gasPrice }( + l1Gateway.outboundTransfer{ value: retryableCost }( address(token), user, depositAmount, maxGas, - gasPrice, + gasPriceBid, routerEncodedData ); @@ -135,14 +125,10 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); // retryable params - uint256 maxSubmissionCost = 2; - uint256 maxGas = 2000000000; - uint256 gasPrice = 7; uint256 depositAmount = 450; address refundTo = address(2000); bytes memory callHookData = ""; - bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); - bytes memory routerEncodedData = abi.encode(user, userEncodedData); + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); // approve token vm.prank(user); @@ -169,13 +155,13 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { // trigger deposit vm.prank(router); - l1Gateway.outboundTransferCustomRefund{ value: maxSubmissionCost + maxGas * gasPrice }( + l1Gateway.outboundTransferCustomRefund{ value: retryableCost }( address(token), refundTo, user, depositAmount, maxGas, - gasPrice, + gasPriceBid, routerEncodedData ); @@ -191,52 +177,6 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { ); } - function test_outboundTransferCustomRefund_revert_NotFromRouter() public { - vm.expectRevert("NOT_FROM_ROUTER"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( - address(token), - user, - user, - 400, - 0.1 ether, - 0.01 ether, - "" - ); - } - - function test_outboundTransferCustomRefund_revert_ExtraDataDisabled() public { - bytes memory callHookData = abi.encodeWithSignature("doSomething()"); - bytes memory routerEncodedData = buildRouterEncodedData(callHookData); - - vm.prank(router); - vm.expectRevert("EXTRA_DATA_DISABLED"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( - address(token), - user, - user, - 400, - 0.1 ether, - 0.01 ether, - routerEncodedData - ); - } - - function test_outboundTransferCustomRefund_revert_L1NotContract() public { - address invalidTokenAddress = address(70); - - vm.prank(router); - vm.expectRevert("L1_NOT_CONTRACT"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( - address(invalidTokenAddress), - user, - user, - 400, - 0.1 ether, - 0.01 ether, - buildRouterEncodedData("") - ); - } - function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public { uint256 tooManyTokens = 500 ether; @@ -253,57 +193,6 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { ); } - function test_finalizeInboundTransfer() public { - // fund gateway with tokens being withdrawn - vm.prank(address(l1Gateway)); - TestERC20(address(token)).mint(); - - // snapshot state before - uint256 userBalanceBefore = token.balanceOf(user); - uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); - - // withdrawal params - address from = address(3000); - uint256 withdrawalAmount = 25; - 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(address(token), from, user, withdrawalAmount, data); - - // check tokens are properly released - uint256 userBalanceAfter = token.balanceOf(user); - assertEq(userBalanceAfter - userBalanceBefore, withdrawalAmount, "Wrong user balance"); - - uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); - assertEq( - l1GatewayBalanceBefore - l1GatewayBalanceAfter, - withdrawalAmount, - "Wrong l1 gateway balance" - ); - } - - function test_finalizeInboundTransfer_revert_NotFromBridge() public { - address notBridge = address(300); - vm.prank(notBridge); - vm.expectRevert("NOT_FROM_BRIDGE"); - l1Gateway.finalizeInboundTransfer(address(token), user, user, 100, ""); - } - - function test_finalizeInboundTransfer_revert_OnlyCounterpartGateway() public { - address notCounterPartGateway = address(400); - InboxMock(address(inbox)).setL2ToL1Sender(notCounterPartGateway); - - // trigger withdrawal - vm.prank(address(IInbox(l1Gateway.inbox()).bridge())); - vm.expectRevert("ONLY_COUNTERPART_GATEWAY"); - l1Gateway.finalizeInboundTransfer(address(token), user, user, 100, ""); - } - function test_getOutboundCalldata() public { bytes memory outboundCalldata = l1Gateway.getOutboundCalldata({ _token: address(token), @@ -328,18 +217,6 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { assertEq(outboundCalldata, expectedCalldata, "Invalid outboundCalldata"); } - function test_supportsInterface(bytes4 iface) public { - bool expected = false; - if ( - iface == type(IERC165).interfaceId || - iface == IL1ArbitrumGateway.outboundTransferCustomRefund.selector - ) { - expected = true; - } - - assertEq(l1Gateway.supportsInterface(iface), expected, "Interface shouldn't be supported"); - } - function test_calculateL2TokenAddress(address tokenAddress) public { address l2TokenAddress = l1Gateway.calculateL2TokenAddress(tokenAddress); @@ -352,25 +229,6 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { assertEq(l2TokenAddress, expectedL2TokenAddress, "Invalid calculateL2TokenAddress"); } - function test_postUpgradeInit_revert_NotFromAdmin() public { - vm.expectRevert("NOT_FROM_ADMIN"); - L1ERC20Gateway(address(l1Gateway)).postUpgradeInit(); - } - - //// - // Helper functions - //// - function buildRouterEncodedData( - bytes memory callHookData - ) internal view virtual returns (bytes memory) { - uint256 maxSubmissionCost = 20; - - bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); - bytes memory routerEncodedData = abi.encode(user, userEncodedData); - - return routerEncodedData; - } - //// // Event declarations //// diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 3c1c72e16b..f8aa8888f7 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -188,7 +188,6 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { bytes memory callHookData ) internal view override returns (bytes memory) { uint256 nativeTokenTotalFee = 350; - uint256 maxSubmissionCost = 20; bytes memory userEncodedData = abi.encode( maxSubmissionCost, From 25ce3ab04d5e8b01d639cb1946c6288b7674e41f Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 4 May 2023 17:35:06 +0200 Subject: [PATCH 053/163] Implement test cases for L1OrbitCustomGatewayTest --- contracts/tokenbridge/test/InboxMock.sol | 7 +- test-foundry/L1ArbitrumExtendedGateway.t.sol | 4 + test-foundry/L1CustomGateway.t.sol | 248 +++++---- test-foundry/L1GatewayRouter.t.sol | 8 +- test-foundry/L1OrbitCustomGateway.t.sol | 497 +++++++++++++++++++ test-foundry/L1OrbitERC20Gateway.t.sol | 47 +- 6 files changed, 645 insertions(+), 166 deletions(-) create mode 100644 test-foundry/L1OrbitCustomGateway.t.sol diff --git a/contracts/tokenbridge/test/InboxMock.sol b/contracts/tokenbridge/test/InboxMock.sol index b01280c980..bb684b003a 100644 --- a/contracts/tokenbridge/test/InboxMock.sol +++ b/contracts/tokenbridge/test/InboxMock.sol @@ -22,7 +22,8 @@ import "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import "@arbitrum/nitro-contracts/src/bridge/IBridge.sol"; abstract contract AbsInboxMock { - address l2ToL1SenderMock = address(0); + address public l2ToL1SenderMock = address(0); + uint256 public seqNum = 0; event TicketData(uint256 maxSubmissionCost); event RefundAddresses(address excessFeeRefundAddress, address callValueRefundAddress); @@ -62,7 +63,7 @@ contract InboxMock is AbsInboxMock { emit TicketData(maxSubmissionCost); emit RefundAddresses(excessFeeRefundAddress, callValueRefundAddress); emit InboxRetryableTicket(msg.sender, to, l2CallValue, gasLimit, data); - return 0; + return seqNum++; } } @@ -104,6 +105,6 @@ contract ERC20InboxMock is AbsInboxMock { tokenTotalFeeAmount, data ); - return 0; + return seqNum++; } } diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol index 10f44f6df9..37d320eac7 100644 --- a/test-foundry/L1ArbitrumExtendedGateway.t.sol +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -23,6 +23,10 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { uint256 public retryableCost; address public creditBackAddress = makeAddr("creditBackAddress"); + // fuzzer behaves weirdly when it picks up this address which is used internally for issuing cheatcodes + address internal constant FOUNDRY_CHEATCODE_ADDRESS = + 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D; + /* solhint-disable func-name-mixedcase */ function test_encodeWithdrawal(uint256 exitNum, address dest) public { bytes32 encodedWithdrawal = L1ArbitrumExtendedGateway(address(l1Gateway)).encodeWithdrawal( diff --git a/test-foundry/L1CustomGateway.t.sol b/test-foundry/L1CustomGateway.t.sol index 2f3d13cc2d..28012fc778 100644 --- a/test-foundry/L1CustomGateway.t.sol +++ b/test-foundry/L1CustomGateway.t.sol @@ -3,11 +3,10 @@ pragma solidity ^0.8.0; import { L1ArbitrumExtendedGatewayTest } from "./L1ArbitrumExtendedGateway.t.sol"; -import { L1CustomGateway, IInbox, ITokenGateway, IERC165, IL1ArbitrumGateway } from "contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol"; +import { L1CustomGateway, IInbox, ITokenGateway, IERC165, IL1ArbitrumGateway, IERC20 } from "contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol"; import { L2CustomGateway } from "contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol"; import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; import { InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { // gateway params @@ -33,7 +32,7 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { } /* solhint-disable func-name-mixedcase */ - function test_calculateL2TokenAddress(address l1Token, address l2Token) public { + function test_calculateL2TokenAddress(address l1Token, address l2Token) public virtual { vm.deal(l1Token, 100 ether); // register token to gateway @@ -54,6 +53,102 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { assertEq(l1Gateway.calculateL2TokenAddress(l1Token), l2Token, "Invalid L2 token address"); } + function test_forceRegisterTokenToL2() public virtual { + address[] memory l1Tokens = new address[](2); + l1Tokens[0] = makeAddr("l1Token1"); + l1Tokens[1] = makeAddr("l1Token2"); + address[] memory l2Tokens = new address[](2); + l2Tokens[0] = makeAddr("l2Token1"); + l2Tokens[1] = makeAddr("l2Token2"); + + // expect events + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Tokens[0], l2Tokens[0]); + + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Tokens[1], l2Tokens[1]); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + emit InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + abi.encodeWithSelector(L2CustomGateway.registerTokenFromL1.selector, l1Tokens, l2Tokens) + ); + + // register token to gateway + vm.prank(owner); + uint256 seqNum = L1CustomGateway(address(l1Gateway)).forceRegisterTokenToL2{ + value: retryableCost + }(l1Tokens, l2Tokens, maxGas, gasPriceBid, maxSubmissionCost); + + ///// checks + assertEq( + L1CustomGateway(address(l1Gateway)).l1ToL2Token(l1Tokens[0]), + l2Tokens[0], + "Invalid L2 token" + ); + + assertEq( + L1CustomGateway(address(l1Gateway)).l1ToL2Token(l1Tokens[1]), + l2Tokens[1], + "Invalid L2 token" + ); + + assertEq(seqNum, 0, "Invalid seqNum"); + } + + function test_forceRegisterTokenToL2_revert_InvalidLength() public virtual { + vm.prank(owner); + vm.expectRevert("INVALID_LENGTHS"); + L1CustomGateway(address(l1Gateway)).forceRegisterTokenToL2{ value: retryableCost }( + new address[](1), + new address[](2), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + + function test_forceRegisterTokenToL2_revert_OnlyOwner() public { + vm.expectRevert("ONLY_OWNER"); + L1CustomGateway(address(l1Gateway)).forceRegisterTokenToL2{ value: retryableCost }( + new address[](1), + new address[](1), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + + function test_getOutboundCalldata() public { + bytes memory outboundCalldata = l1Gateway.getOutboundCalldata({ + _token: address(token), + _from: user, + _to: address(800), + _amount: 355, + _data: abi.encode("doStuff()") + }); + + bytes memory expectedCalldata = abi.encodeWithSelector( + ITokenGateway.finalizeInboundTransfer.selector, + address(token), + user, + address(800), + 355, + abi.encode("", abi.encode("doStuff()")) + ); + + assertEq(outboundCalldata, expectedCalldata, "Invalid outboundCalldata"); + } + function test_initialize() public virtual { L1CustomGateway gateway = new L1CustomGateway(); gateway.initialize(l2Gateway, router, inbox, owner); @@ -81,13 +176,9 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { abi.encode(uint8(0xb1)) ); vm.prank(address(token)); - L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( - makeAddr("tokenL2Address"), - maxGas, - gasPriceBid, - maxSubmissionCost, - makeAddr("creditBackAddress") - ); + uint256 seqNum0 = L1CustomGateway(address(l1Gateway)).registerTokenToL2{ + value: retryableCost + }(makeAddr("tokenL2Address"), maxGas, gasPriceBid, maxSubmissionCost, creditBackAddress); // approve token vm.prank(user); @@ -110,11 +201,11 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { ); vm.expectEmit(true, true, true, true); - emit DepositInitiated(address(token), user, user, 0, depositAmount); + emit DepositInitiated(address(token), user, user, 1, depositAmount); // trigger deposit vm.prank(router); - l1Gateway.outboundTransfer{ value: retryableCost }( + bytes memory seqNum1 = l1Gateway.outboundTransfer{ value: retryableCost }( address(token), user, depositAmount, @@ -133,6 +224,9 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { depositAmount, "Wrong l1 gateway balance" ); + + assertEq(seqNum0, 0, "Invalid seqNum0"); + assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); } function test_outboundTransferCustomRefund() public virtual { @@ -141,7 +235,6 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); uint256 depositAmount = 450; - address refundTo = address(2000); bytes memory callHookData = ""; bytes memory routerEncodedData = buildRouterEncodedData(callHookData); @@ -152,13 +245,9 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { abi.encode(uint8(0xb1)) ); vm.prank(address(token)); - L1CustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( - makeAddr("tokenL2Address"), - maxGas, - gasPriceBid, - maxSubmissionCost, - makeAddr("creditBackAddress") - ); + uint256 seqNum0 = L1CustomGateway(address(l1Gateway)).registerTokenToL2{ + value: retryableCost + }(makeAddr("tokenL2Address"), maxGas, gasPriceBid, maxSubmissionCost, creditBackAddress); // approve token vm.prank(user); @@ -169,7 +258,7 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { emit TicketData(maxSubmissionCost); vm.expectEmit(true, true, true, true); - emit RefundAddresses(refundTo, user); + emit RefundAddresses(creditBackAddress, user); vm.expectEmit(true, true, true, true); emit InboxRetryableTicket( @@ -181,13 +270,13 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { ); vm.expectEmit(true, true, true, true); - emit DepositInitiated(address(token), user, user, 0, depositAmount); + emit DepositInitiated(address(token), user, user, 1, depositAmount); // trigger deposit vm.prank(router); - l1Gateway.outboundTransferCustomRefund{ value: retryableCost }( + bytes memory seqNum1 = l1Gateway.outboundTransferCustomRefund{ value: retryableCost }( address(token), - refundTo, + creditBackAddress, user, depositAmount, maxGas, @@ -205,9 +294,12 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { depositAmount, "Wrong l1 gateway balance" ); + + assertEq(seqNum0, 0, "Invalid seqNum0"); + assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); } - function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public { + function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public virtual { uint256 tooManyTokens = 500 ether; // register token to gateway @@ -238,103 +330,8 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { ); } - function test_forceRegisterTokenToL2() public { - address[] memory l1Tokens = new address[](2); - l1Tokens[0] = makeAddr("l1Token1"); - l1Tokens[1] = makeAddr("l1Token2"); - address[] memory l2Tokens = new address[](2); - l2Tokens[0] = makeAddr("l2Token1"); - l2Tokens[1] = makeAddr("l2Token2"); - - // expect events - vm.expectEmit(true, true, true, true); - emit TokenSet(l1Tokens[0], l2Tokens[0]); - - vm.expectEmit(true, true, true, true); - emit TokenSet(l1Tokens[1], l2Tokens[1]); - - vm.expectEmit(true, true, true, true); - emit TicketData(maxSubmissionCost); - - vm.expectEmit(true, true, true, true); - emit RefundAddresses(owner, owner); - - vm.expectEmit(true, true, true, true); - emit InboxRetryableTicket( - address(l1Gateway), - l2Gateway, - 0, - maxGas, - abi.encodeWithSelector(L2CustomGateway.registerTokenFromL1.selector, l1Tokens, l2Tokens) - ); - - // register token to gateway - vm.prank(owner); - uint256 seqNum = L1CustomGateway(address(l1Gateway)).forceRegisterTokenToL2{ - value: retryableCost - }(l1Tokens, l2Tokens, maxGas, gasPriceBid, maxSubmissionCost); - - ///// checks - assertEq( - L1CustomGateway(address(l1Gateway)).l1ToL2Token(l1Tokens[0]), - l2Tokens[0], - "Invalid L2 token" - ); - - assertEq( - L1CustomGateway(address(l1Gateway)).l1ToL2Token(l1Tokens[1]), - l2Tokens[1], - "Invalid L2 token" - ); - - assertEq(seqNum, 0, "Invalid seqNum"); - } - - function test_forceRegisterTokenToL2_revert_InvalidLength() public { - vm.prank(owner); - vm.expectRevert("INVALID_LENGTHS"); - L1CustomGateway(address(l1Gateway)).forceRegisterTokenToL2{ value: retryableCost }( - new address[](1), - new address[](2), - maxGas, - gasPriceBid, - maxSubmissionCost - ); - } - - function test_forceRegisterTokenToL2_revert_OnlyOwner() public { - vm.expectRevert("ONLY_OWNER"); - L1CustomGateway(address(l1Gateway)).forceRegisterTokenToL2{ value: retryableCost }( - new address[](1), - new address[](1), - maxGas, - gasPriceBid, - maxSubmissionCost - ); - } - - function test_getOutboundCalldata() public { - bytes memory outboundCalldata = l1Gateway.getOutboundCalldata({ - _token: address(token), - _from: user, - _to: address(800), - _amount: 355, - _data: abi.encode("doStuff()") - }); - - bytes memory expectedCalldata = abi.encodeWithSelector( - ITokenGateway.finalizeInboundTransfer.selector, - address(token), - user, - address(800), - 355, - abi.encode("", abi.encode("doStuff()")) - ); - - assertEq(outboundCalldata, expectedCalldata, "Invalid outboundCalldata"); - } - - function test_registerTokenToL2(address l1Token, address l2Token) public { + function test_registerTokenToL2(address l1Token, address l2Token) public virtual { + vm.assume(l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS); vm.deal(l1Token, 100 ether); // event checkers @@ -381,7 +378,8 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { ); } - function test_registerTokenToL2_CustomRefund(address l1Token, address l2Token) public { + function test_registerTokenToL2_CustomRefund(address l1Token, address l2Token) public virtual { + vm.assume(l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS); vm.deal(l1Token, 100 ether); // event checkers @@ -429,7 +427,7 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { ); } - function test_registerTokenToL2_revert_NotArbEnabled() public { + function test_registerTokenToL2_revert_NotArbEnabled() public virtual { // wrong answer vm.mockCall( address(token), @@ -448,7 +446,7 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { ); } - function test_registerTokenToL2_revert_NoUpdateToDifferentAddress() public { + function test_registerTokenToL2_revert_NoUpdateToDifferentAddress() public virtual { // register token to gateway vm.mockCall( address(token), diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 858243e739..89b483569f 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -268,7 +268,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { "Gateway not set" ); - assertEq(seqNum, 0, "Invalid seqNum"); + assertEq(seqNum, 1, "Invalid seqNum"); } function test_setGateway_CustomCreditback() public virtual { @@ -337,7 +337,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { "Gateway not set" ); - assertEq(seqNum, 0, "Invalid seqNum"); + assertEq(seqNum, 1, "Invalid seqNum"); } function test_setGateway_revert_NotArbEnabled() public virtual { @@ -529,7 +529,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { assertEq(l1Router.l1TokenToGateway(tokens[0]), gateways[0], "Gateway[0] not set"); assertEq(l1Router.l1TokenToGateway(tokens[1]), gateways[1], "Gateway[1] not set"); - assertEq(seqNum, 0, "Invalid seqNum"); + assertEq(seqNum, 2, "Invalid seqNum"); } function test_setGateways_revert_WrongLength() public virtual { @@ -631,7 +631,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { ///// checks assertEq(l1Router.l1TokenToGateway(token), address(0), "Custom gateway not cleared"); - assertEq(seqNum, 0, "Invalid seqNum"); + assertEq(seqNum, 2, "Invalid seqNum"); } function test_setGateways_revert_notOwner() public { diff --git a/test-foundry/L1OrbitCustomGateway.t.sol b/test-foundry/L1OrbitCustomGateway.t.sol new file mode 100644 index 0000000000..93226cafeb --- /dev/null +++ b/test-foundry/L1OrbitCustomGateway.t.sol @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import { L1CustomGatewayTest, IERC20, L2CustomGateway } from "./L1CustomGateway.t.sol"; +import { L1OrbitCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol"; + +import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; +import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; + +contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { + uint256 public nativeTokenTotalFee; + + function setUp() public override { + inbox = address(new ERC20InboxMock()); + + l1Gateway = new L1OrbitCustomGateway(); + L1OrbitCustomGateway(address(l1Gateway)).initialize(l2Gateway, router, inbox, owner); + + token = IERC20(address(new TestERC20())); + + maxSubmissionCost = 0; + nativeTokenTotalFee = maxGas * gasPriceBid; + + // fund user and router + vm.prank(user); + TestERC20(address(token)).mint(); + vm.deal(router, 100 ether); + vm.deal(address(token), 100 ether); + vm.deal(owner, 100 ether); + } + + /* solhint-disable func-name-mixedcase */ + function test_calculateL2TokenAddress(address l1Token, address l2Token) public override { + vm.deal(l1Token, 100 ether); + + // register token to gateway + vm.mockCall( + address(l1Token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(l1Token)); + L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + l2Token, + maxGas, + gasPriceBid, + maxSubmissionCost, + makeAddr("creditBackAddress"), + nativeTokenTotalFee + ); + + assertEq(l1Gateway.calculateL2TokenAddress(l1Token), l2Token, "Invalid L2 token address"); + } + + function test_forceRegisterTokenToL2() public override { + address[] memory l1Tokens = new address[](2); + l1Tokens[0] = makeAddr("l1Token1"); + l1Tokens[1] = makeAddr("l1Token2"); + address[] memory l2Tokens = new address[](2); + l2Tokens[0] = makeAddr("l2Token1"); + l2Tokens[1] = makeAddr("l2Token2"); + + // expect events + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Tokens[0], l2Tokens[0]); + + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Tokens[1], l2Tokens[1]); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + abi.encodeWithSelector(L2CustomGateway.registerTokenFromL1.selector, l1Tokens, l2Tokens) + ); + + // register token to gateway + vm.prank(owner); + uint256 seqNum = L1OrbitCustomGateway(address(l1Gateway)).forceRegisterTokenToL2( + l1Tokens, + l2Tokens, + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + ///// checks + assertEq( + L1OrbitCustomGateway(address(l1Gateway)).l1ToL2Token(l1Tokens[0]), + l2Tokens[0], + "Invalid L2 token" + ); + + assertEq( + L1OrbitCustomGateway(address(l1Gateway)).l1ToL2Token(l1Tokens[1]), + l2Tokens[1], + "Invalid L2 token" + ); + + assertEq(seqNum, 0, "Invalid seqNum"); + } + + function test_forceRegisterTokenToL2_revert_InvalidLength() public override { + vm.prank(owner); + vm.expectRevert("INVALID_LENGTHS"); + L1OrbitCustomGateway(address(l1Gateway)).forceRegisterTokenToL2( + new address[](1), + new address[](2), + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + } + + function test_outboundTransfer() public override { + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + uint256 depositAmount = 300; + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(token)); + uint256 seqNum0 = L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + // approve token + vm.prank(user); + token.approve(address(l1Gateway), depositAmount); + + // 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(address(token), user, user, depositAmount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(token), user, user, 1, depositAmount); + + // trigger deposit + vm.prank(router); + bytes memory seqNum1 = l1Gateway.outboundTransfer( + address(token), + user, + depositAmount, + maxGas, + gasPriceBid, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + + assertEq(seqNum0, 0, "Invalid seqNum0"); + assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); + } + + function test_outboundTransferCustomRefund() public override { + // snapshot state before + uint256 userBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); + + uint256 depositAmount = 450; + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(token)); + uint256 seqNum0 = L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + // approve token + vm.prank(user); + token.approve(address(l1Gateway), depositAmount); + + // 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(address(token), user, user, depositAmount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(token), user, user, 1, depositAmount); + + // trigger deposit + vm.prank(router); + bytes memory seqNum1 = l1Gateway.outboundTransferCustomRefund( + address(token), + creditBackAddress, + user, + depositAmount, + maxGas, + gasPriceBid, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = token.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, depositAmount, "Wrong user balance"); + + uint256 l1GatewayBalanceAfter = token.balanceOf(address(l1Gateway)); + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + depositAmount, + "Wrong l1 gateway balance" + ); + + assertEq(seqNum0, 0, "Invalid seqNum0"); + assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); + } + + function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public override { + uint256 tooManyTokens = 500 ether; + + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(token)); + L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + vm.prank(router); + vm.expectRevert("ERC20: insufficient allowance"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(token), + user, + user, + tooManyTokens, + 0.1 ether, + 0.01 ether, + buildRouterEncodedData("") + ); + } + + function test_registerTokenToL2(address l1Token, address l2Token) public override { + vm.assume(l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS); + vm.deal(l1Token, 100 ether); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Token, l2Token); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(l1Token, l1Token); + + address[] memory l1Tokens = new address[](1); + l1Tokens[0] = address(l1Token); + address[] memory l2Tokens = new address[](1); + l2Tokens[0] = address(l2Token); + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + abi.encodeWithSelector(L2CustomGateway.registerTokenFromL1.selector, l1Tokens, l2Tokens) + ); + + // register token to gateway + vm.mockCall( + address(l1Token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(l1Token)); + L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + l2Token, + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + assertEq( + L1OrbitCustomGateway(address(l1Gateway)).l1ToL2Token(l1Token), + l2Token, + "Invalid L2 token" + ); + } + + function test_registerTokenToL2_CustomRefund(address l1Token, address l2Token) public override { + vm.assume(l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS); + vm.deal(l1Token, 100 ether); + + // event checkers + vm.expectEmit(true, true, true, true); + emit TokenSet(l1Token, l2Token); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(creditBackAddress, creditBackAddress); + + address[] memory l1Tokens = new address[](1); + l1Tokens[0] = address(l1Token); + address[] memory l2Tokens = new address[](1); + l2Tokens[0] = address(l2Token); + vm.expectEmit(true, true, true, true); + emit ERC20InboxRetryableTicket( + address(l1Gateway), + l2Gateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + abi.encodeWithSelector(L2CustomGateway.registerTokenFromL1.selector, l1Tokens, l2Tokens) + ); + + // register token to gateway + vm.mockCall( + address(l1Token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(l1Token)); + L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + l2Token, + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + assertEq( + L1OrbitCustomGateway(address(l1Gateway)).l1ToL2Token(l1Token), + l2Token, + "Invalid L2 token" + ); + } + + function test_registerTokenToL2_revert_NotArbEnabled() public override { + // wrong answer + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xdd)) + ); + + vm.prank(address(token)); + vm.expectRevert("NOT_ARB_ENABLED"); + L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + address(102), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + } + + function test_registerTokenToL2_revert_NoUpdateToDifferentAddress() public override { + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + + // set initial address + address initialL2TokenAddress = makeAddr("initial"); + vm.prank(address(token)); + L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + initialL2TokenAddress, + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + assertEq( + L1OrbitCustomGateway(address(l1Gateway)).l1ToL2Token(address(token)), + initialL2TokenAddress + ); + + // try to set different one + address differentL2TokenAddress = makeAddr("different"); + vm.prank(address(token)); + vm.expectRevert("NO_UPDATE_TO_DIFFERENT_ADDR"); + L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + differentL2TokenAddress, + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + } + + /// + // 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/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index f8aa8888f7..0b83d9ccf3 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -9,6 +9,8 @@ import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { + uint256 public nativeTokenTotalFee; + function setUp() public override { inbox = address(new ERC20InboxMock()); @@ -22,6 +24,8 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { ); token = IERC20(address(new TestERC20())); + maxSubmissionCost = 0; + nativeTokenTotalFee = maxGas * gasPriceBid; // fund user and router vm.prank(user); @@ -47,20 +51,9 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); // retryable params - uint256 maxSubmissionCost = 0; - uint256 maxGas = 1000000000; - uint256 gasPrice = 3; - uint256 depositAmount = 300; - uint256 nativeTokenTotalFee = maxGas * gasPrice; - bytes memory callHookData = ""; - bytes memory userEncodedData = abi.encode( - maxSubmissionCost, - callHookData, - nativeTokenTotalFee - ); - bytes memory routerEncodedData = abi.encode(user, userEncodedData); + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); // approve token vm.prank(user); @@ -79,7 +72,7 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { l2Gateway, 0, maxGas, - gasPrice, + gasPriceBid, nativeTokenTotalFee, l1Gateway.getOutboundCalldata(address(token), user, user, 300, "") ); @@ -94,7 +87,7 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { user, depositAmount, maxGas, - gasPrice, + gasPriceBid, routerEncodedData ); @@ -116,21 +109,9 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); // retryable params - uint256 maxSubmissionCost = 0; - uint256 maxGas = 200000000; - uint256 gasPrice = 4; - uint256 depositAmount = 700; - uint256 nativeTokenTotalFee = maxGas * gasPrice; - address refundTo = address(3000); - bytes memory callHookData = ""; - bytes memory userEncodedData = abi.encode( - maxSubmissionCost, - callHookData, - nativeTokenTotalFee - ); - bytes memory routerEncodedData = abi.encode(user, userEncodedData); + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); // approve token vm.prank(user); @@ -141,7 +122,7 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { emit TicketData(maxSubmissionCost); vm.expectEmit(true, true, true, true); - emit RefundAddresses(refundTo, user); + emit RefundAddresses(creditBackAddress, user); vm.expectEmit(true, true, true, true); emit ERC20InboxRetryableTicket( @@ -149,7 +130,7 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { l2Gateway, 0, maxGas, - gasPrice, + gasPriceBid, nativeTokenTotalFee, l1Gateway.getOutboundCalldata(address(token), user, user, 700, "") ); @@ -161,11 +142,11 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { vm.prank(router); l1Gateway.outboundTransferCustomRefund( address(token), - refundTo, + creditBackAddress, user, depositAmount, maxGas, - gasPrice, + gasPriceBid, routerEncodedData ); @@ -187,8 +168,6 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { function buildRouterEncodedData( bytes memory callHookData ) internal view override returns (bytes memory) { - uint256 nativeTokenTotalFee = 350; - bytes memory userEncodedData = abi.encode( maxSubmissionCost, callHookData, @@ -204,7 +183,7 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { address to, uint256 l2CallValue, uint256 maxGas, - uint256 gasPrice, + uint256 gasPriceBid, uint256 tokenTotalFeeAmount, bytes data ); From d109210c6497fcf29f79b6754b05f3299830d060 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 5 May 2023 13:17:24 +0200 Subject: [PATCH 054/163] Implement missing TCs --- test-foundry/L1CustomGateway.t.sol | 1 + test-foundry/L1GatewayRouter.t.sol | 56 ++- test-foundry/L1OrbitCustomGateway.t.sol | 1 + test-foundry/L1OrbitGatewayRouter.t.sol | 446 ++++++++++++++++++++++-- 4 files changed, 434 insertions(+), 70 deletions(-) diff --git a/test-foundry/L1CustomGateway.t.sol b/test-foundry/L1CustomGateway.t.sol index 28012fc778..ca4f94048d 100644 --- a/test-foundry/L1CustomGateway.t.sol +++ b/test-foundry/L1CustomGateway.t.sol @@ -33,6 +33,7 @@ contract L1CustomGatewayTest is L1ArbitrumExtendedGatewayTest { /* solhint-disable func-name-mixedcase */ function test_calculateL2TokenAddress(address l1Token, address l2Token) public virtual { + vm.assume(l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS); vm.deal(l1Token, 100 ether); // register token to gateway diff --git a/test-foundry/L1GatewayRouter.t.sol b/test-foundry/L1GatewayRouter.t.sol index 89b483569f..ad53629525 100644 --- a/test-foundry/L1GatewayRouter.t.sol +++ b/test-foundry/L1GatewayRouter.t.sol @@ -288,12 +288,12 @@ contract L1GatewayRouterTest is GatewayRouterTest { // register token to gateway vm.prank(address(customToken)); - customGateway.registerTokenToL2{ value: 4000040000 }( + customGateway.registerTokenToL2{ value: retryableCost }( makeAddr("tokenL2Address"), - 1000000000, - 3, - 40000, - makeAddr("creditBackAddress") + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress ); // expect events @@ -369,12 +369,12 @@ contract L1GatewayRouterTest is GatewayRouterTest { vm.prank(token); vm.expectRevert("NOT_TO_CONTRACT"); - l1Router.setGateway{ value: 400000 }( + l1Router.setGateway{ value: retryableCost }( gatewayNotContract, - 100000, - 3, - 200, - makeAddr("creditback") + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress ); } @@ -444,12 +444,12 @@ contract L1GatewayRouterTest is GatewayRouterTest { vm.prank(token); vm.expectRevert("TOKEN_NOT_HANDLED_BY_GATEWAY"); - l1Router.setGateway{ value: 400000 }( + l1Router.setGateway{ value: retryableCost }( address(gateway), - 100000, - 3, - 200, - makeAddr("creditback") + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress ); } @@ -688,7 +688,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { // set default gateway vm.prank(owner); - l1Router.setDefaultGateway{ value: _getValue() }( + l1Router.setDefaultGateway{ value: retryableCost }( address(defaultGateway), maxGas, gasPriceBid, @@ -708,7 +708,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { /// deposit data address to = address(401); uint256 amount = 103; - bytes memory userEncodedData = _buildUserEncodedData(""); + bytes memory userEncodedData = abi.encode(maxSubmissionCost, ""); // expect event vm.expectEmit(true, true, true, true); @@ -716,7 +716,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { /// deposit it vm.prank(user); - l1Router.outboundTransfer{ value: _getValue() }( + l1Router.outboundTransfer{ value: retryableCost }( address(token), to, amount, @@ -749,7 +749,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { // set default gateway vm.prank(owner); - l1Router.setDefaultGateway{ value: _getValue() }( + l1Router.setDefaultGateway{ value: retryableCost }( address(defaultGateway), maxGas, gasPriceBid, @@ -770,7 +770,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { address refundTo = address(400); address to = address(401); uint256 amount = 103; - bytes memory userEncodedData = _buildUserEncodedData(""); + bytes memory userEncodedData = abi.encode(maxSubmissionCost, ""); // expect event vm.expectEmit(true, true, true, true); @@ -778,7 +778,7 @@ contract L1GatewayRouterTest is GatewayRouterTest { /// deposit it vm.prank(user); - l1Router.outboundTransferCustomRefund{ value: _getValue() }( + l1Router.outboundTransferCustomRefund{ value: retryableCost }( address(token), refundTo, to, @@ -800,20 +800,6 @@ contract L1GatewayRouterTest is GatewayRouterTest { ); } - //// - // Helper functions - //// - function _buildUserEncodedData( - bytes memory callHookData - ) internal view virtual returns (bytes memory) { - bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); - return userEncodedData; - } - - function _getValue() internal view virtual returns (uint256) { - return retryableCost; - } - //// // Event declarations //// diff --git a/test-foundry/L1OrbitCustomGateway.t.sol b/test-foundry/L1OrbitCustomGateway.t.sol index 93226cafeb..cd1d5afb83 100644 --- a/test-foundry/L1OrbitCustomGateway.t.sol +++ b/test-foundry/L1OrbitCustomGateway.t.sol @@ -32,6 +32,7 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { /* solhint-disable func-name-mixedcase */ function test_calculateL2TokenAddress(address l1Token, address l2Token) public override { + vm.assume(l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS); vm.deal(l1Token, 100 ether); // register token to gateway diff --git a/test-foundry/L1OrbitGatewayRouter.t.sol b/test-foundry/L1OrbitGatewayRouter.t.sol index 58ddfbf8ab..c593be92a5 100644 --- a/test-foundry/L1OrbitGatewayRouter.t.sol +++ b/test-foundry/L1OrbitGatewayRouter.t.sol @@ -8,7 +8,7 @@ import { L1OrbitERC20Gateway } from "contracts/tokenbridge/ethereum/gateway/L1Or import { L1OrbitGatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol"; import { L2GatewayRouter } from "contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol"; import { L1GatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol"; -import { L1CustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol"; +import { L1OrbitCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol"; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { ERC20PresetMinterPauser } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; @@ -27,7 +27,6 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { l1OrbitRouter.initialize(owner, defaultGateway, address(0), counterpartGateway, inbox); maxSubmissionCost = 0; - retryableCost = 0; nativeTokenTotalFee = gasPriceBid * maxGas; vm.deal(owner, 100 ether); @@ -112,7 +111,7 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { /// deposit data address to = address(401); uint256 amount = 103; - bytes memory userEncodedData = _buildUserEncodedData(""); + bytes memory userEncodedData = abi.encode(maxSubmissionCost, "", nativeTokenTotalFee); // expect event vm.expectEmit(true, true, true, true); @@ -120,14 +119,7 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { /// deposit it vm.prank(user); - l1Router.outboundTransfer{ value: _getValue() }( - address(token), - to, - amount, - maxGas, - gasPriceBid, - userEncodedData - ); + l1Router.outboundTransfer(address(token), to, amount, maxGas, gasPriceBid, userEncodedData); // check tokens are escrowed uint256 userBalanceAfter = token.balanceOf(user); @@ -175,7 +167,7 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { address refundTo = address(400); address to = address(401); uint256 amount = 103; - bytes memory userEncodedData = _buildUserEncodedData(""); + bytes memory userEncodedData = abi.encode(maxSubmissionCost, "", nativeTokenTotalFee); // expect event vm.expectEmit(true, true, true, true); @@ -183,7 +175,7 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { /// deposit it vm.prank(user); - l1Router.outboundTransferCustomRefund{ value: _getValue() }( + l1Router.outboundTransferCustomRefund( address(token), refundTo, to, @@ -316,15 +308,206 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { } function test_setGateway() public override { - // TODO after custom gateway changes + // create gateway + L1OrbitCustomGateway customGateway = new L1OrbitCustomGateway(); + address l2Counterpart = makeAddr("l2Counterpart"); + customGateway.initialize(l2Counterpart, address(l1Router), address(inbox), owner); + + // create token + ERC20 customToken = new ERC20("X", "Y"); + vm.deal(address(customToken), 100 ether); + + // register token to gateway + vm.mockCall( + address(customToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(customToken)); + customGateway.registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + // expect events + vm.expectEmit(true, true, true, true); + emit GatewaySet(address(customToken), address(customGateway)); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(address(customToken), address(customToken)); + + vm.expectEmit(true, true, true, true); + address[] memory _tokenArr = new address[](1); + _tokenArr[0] = address(customToken); + address[] memory _gatewayArr = new address[](1); + _gatewayArr[0] = l2Counterpart; + emit ERC20InboxRetryableTicket( + address(l1OrbitRouter), + counterpartGateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + abi.encodeWithSelector(L2GatewayRouter.setGateway.selector, _tokenArr, _gatewayArr) + ); + + // set gateway + vm.prank(address(customToken)); + uint256 seqNum = l1OrbitRouter.setGateway( + address(customGateway), + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + ///// checks + + assertEq( + l1OrbitRouter.l1TokenToGateway(address(customToken)), + address(customGateway), + "Gateway not set" + ); + + assertEq(seqNum, 1, "Invalid seqNum"); } function test_setGateway_CustomCreditback() public override { - // TODO after custom gateway changes + // create gateway + L1OrbitCustomGateway customGateway = new L1OrbitCustomGateway(); + address l2Counterpart = makeAddr("l2Counterpart"); + customGateway.initialize(l2Counterpart, address(l1Router), address(inbox), owner); + + // create token + ERC20 customToken = new ERC20("X", "Y"); + vm.deal(address(customToken), 100 ether); + + // register token to gateway + vm.mockCall( + address(customToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(address(customToken)); + customGateway.registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + // expect events + vm.expectEmit(true, true, true, true); + emit GatewaySet(address(customToken), address(customGateway)); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(creditBackAddress, creditBackAddress); + + vm.expectEmit(true, true, true, true); + address[] memory _tokenArr = new address[](1); + _tokenArr[0] = address(customToken); + address[] memory _gatewayArr = new address[](1); + _gatewayArr[0] = l2Counterpart; + emit ERC20InboxRetryableTicket( + address(l1OrbitRouter), + counterpartGateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + abi.encodeWithSelector(L2GatewayRouter.setGateway.selector, _tokenArr, _gatewayArr) + ); + + // set gateway + vm.prank(address(customToken)); + uint256 seqNum = l1OrbitRouter.setGateway( + address(customGateway), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + ///// checks + + assertEq( + l1OrbitRouter.l1TokenToGateway(address(customToken)), + address(customGateway), + "Gateway not set" + ); + + assertEq(seqNum, 1, "Invalid seqNum"); } function test_setGateway_revert_NoUpdateToDifferentAddress() public override { - // TODO after custom gateway changes + // create gateway + address initialGateway = address(new L1OrbitCustomGateway()); + address l2Counterpart = makeAddr("l2Counterpart"); + L1OrbitCustomGateway(initialGateway).initialize( + l2Counterpart, + address(l1Router), + address(inbox), + owner + ); + + // create token + address token = address(new ERC20("X", "Y")); + vm.deal(address(token), 100 ether); + + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(token); + L1OrbitCustomGateway(initialGateway).registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + // initially set gateway for token + vm.prank(address(token)); + l1OrbitRouter.setGateway( + initialGateway, + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + assertEq(l1OrbitRouter.l1TokenToGateway(token), initialGateway, "Initial gateway not set"); + + //// now try setting different gateway + address newGateway = address(new L1OrbitCustomGateway()); + + vm.prank(token); + vm.expectRevert("NO_UPDATE_TO_DIFFERENT_ADDR"); + l1OrbitRouter.setGateway( + newGateway, + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); } function test_setGateway_revert_NotArbEnabled() public override { @@ -349,41 +532,234 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { } function test_setGateway_revert_NotToContract() public override { - // TODO after custom gateway changes + address token = address(new ERC20("X", "Y")); + vm.deal(token, 100 ether); + vm.mockCall(token, abi.encodeWithSignature("isArbitrumEnabled()"), abi.encode(uint8(0xb1))); + + address gatewayNotContract = makeAddr("not contract"); + + vm.prank(token); + vm.expectRevert("NOT_TO_CONTRACT"); + l1OrbitRouter.setGateway( + gatewayNotContract, + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); } function test_setGateway_revert_TokenNotHandledByGateway() public override { - // TODO after custom gateway changes + // create gateway + L1OrbitCustomGateway gateway = new L1OrbitCustomGateway(); + + // create token + address token = address(new ERC20("X", "Y")); + vm.deal(token, 100 ether); + vm.mockCall(token, abi.encodeWithSignature("isArbitrumEnabled()"), abi.encode(uint8(0xb1))); + + vm.prank(token); + vm.expectRevert("TOKEN_NOT_HANDLED_BY_GATEWAY"); + l1OrbitRouter.setGateway( + address(gateway), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); } function test_setGateways() public override { - // TODO after custom gateway changes + // create tokens and gateways + address[] memory tokens = new address[](2); + tokens[0] = address(new ERC20("1", "1")); + tokens[1] = address(new ERC20("2", "2")); + address[] memory gateways = new address[](2); + gateways[0] = address(new L1OrbitCustomGateway()); + gateways[1] = address(new L1OrbitCustomGateway()); + + address l2Counterpart = makeAddr("l2Counterpart"); + + /// init all + for (uint256 i = 0; i < 2; i++) { + L1OrbitCustomGateway(gateways[i]).initialize( + l2Counterpart, + address(l1Router), + address(inbox), + owner + ); + + vm.mockCall( + tokens[i], + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + + // register tokens to gateways + vm.deal(tokens[i], 100 ether); + vm.prank(tokens[i]); + L1OrbitCustomGateway(gateways[i]).registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + } + + // expect events + vm.expectEmit(true, true, true, true); + emit GatewaySet(tokens[0], gateways[0]); + vm.expectEmit(true, true, true, true); + emit GatewaySet(tokens[1], gateways[1]); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); + + vm.expectEmit(true, true, true, true); + address[] memory _gatewayArr = new address[](2); + _gatewayArr[0] = l2Counterpart; + _gatewayArr[1] = l2Counterpart; + emit ERC20InboxRetryableTicket( + address(l1OrbitRouter), + counterpartGateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + abi.encodeWithSelector(L2GatewayRouter.setGateway.selector, tokens, _gatewayArr) + ); + + /// set gateways + vm.prank(owner); + uint256 seqNum = l1OrbitRouter.setGateways( + tokens, + gateways, + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + ///// checks + + assertEq(l1Router.l1TokenToGateway(tokens[0]), gateways[0], "Gateway[0] not set"); + assertEq(l1Router.l1TokenToGateway(tokens[1]), gateways[1], "Gateway[1] not set"); + assertEq(seqNum, 2, "Invalid seqNum"); } function test_setGateways_SetZeroAddr() public override { - // TODO after custom gateway changes - } + // create gateway + address initialGateway = address(new L1OrbitCustomGateway()); + address l2Counterpart = makeAddr("l2Counterpart"); + L1OrbitCustomGateway(initialGateway).initialize( + l2Counterpart, + address(l1Router), + address(inbox), + owner + ); - function test_setGateways_revert_WrongLength() public override { - // TODO after custom gateway changes - } + // create token + address token = address(new ERC20("X", "Y")); + vm.deal(address(token), 100 ether); + + // register token to gateway + vm.mockCall( + address(token), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.prank(token); + L1OrbitCustomGateway(initialGateway).registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + // initially set gateway for token + vm.prank(address(token)); + l1OrbitRouter.setGateway( + initialGateway, + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + assertEq(l1OrbitRouter.l1TokenToGateway(token), initialGateway, "Initial gateway not set"); + + //// now set to zero addr + address newGateway = address(0); + + // expect events + vm.expectEmit(true, true, true, true); + emit GatewaySet(token, newGateway); + + vm.expectEmit(true, true, true, true); + emit TicketData(maxSubmissionCost); + + vm.expectEmit(true, true, true, true); + emit RefundAddresses(owner, owner); - //// - // Helper functions - //// - function _buildUserEncodedData( - bytes memory callHookData - ) internal view override returns (bytes memory) { - bytes memory userEncodedData = abi.encode( + vm.expectEmit(true, true, true, true); + address[] memory _tokenArr = new address[](1); + _tokenArr[0] = token; + address[] memory _gatewayArr = new address[](1); + _gatewayArr[0] = newGateway; + emit ERC20InboxRetryableTicket( + address(l1OrbitRouter), + counterpartGateway, + 0, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + abi.encodeWithSelector(L2GatewayRouter.setGateway.selector, _tokenArr, _gatewayArr) + ); + + /// set gateways + vm.prank(owner); + uint256 seqNum = l1OrbitRouter.setGateways( + _tokenArr, + _gatewayArr, + maxGas, + gasPriceBid, maxSubmissionCost, - callHookData, nativeTokenTotalFee ); - return userEncodedData; + + ///// checks + + assertEq(l1OrbitRouter.l1TokenToGateway(token), address(0), "Custom gateway not cleared"); + assertEq(seqNum, 2, "Invalid seqNum"); } - function _getValue() internal pure override returns (uint256) { - return 0; + function test_setGateways_revert_WrongLength() public override { + address[] memory tokens = new address[](2); + tokens[0] = address(new ERC20("1", "1")); + tokens[1] = address(new ERC20("2", "2")); + address[] memory gateways = new address[](1); + gateways[0] = address(new L1OrbitCustomGateway()); + + /// set gateways + vm.prank(owner); + vm.expectRevert("WRONG_LENGTH"); + l1OrbitRouter.setGateways( + tokens, + gateways, + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); } event ERC20InboxRetryableTicket( From 8b8645f5856cda20eef3d8913363867ecb4af75c Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 5 May 2023 14:02:49 +0200 Subject: [PATCH 055/163] Check functions without nativeTokenFee are reverting --- test-foundry/L1OrbitCustomGateway.t.sol | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test-foundry/L1OrbitCustomGateway.t.sol b/test-foundry/L1OrbitCustomGateway.t.sol index cd1d5afb83..1779e46403 100644 --- a/test-foundry/L1OrbitCustomGateway.t.sol +++ b/test-foundry/L1OrbitCustomGateway.t.sol @@ -126,6 +126,19 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { ); } + function test_forceRegisterTokenToL2_revert_NotSupportedInOrbit() public { + // register token to gateway + vm.prank(owner); + vm.expectRevert("NOT_SUPPORTED_IN_ORBIT"); + L1OrbitCustomGateway(address(l1Gateway)).forceRegisterTokenToL2( + new address[](1), + new address[](1), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + function test_outboundTransfer() public override { // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); @@ -470,6 +483,27 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { ); } + function test_registerTokenToL2_revert_NotSupportedInOrbit() public { + vm.expectRevert("NOT_SUPPORTED_IN_ORBIT"); + L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + address(100), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + + function test_registerTokenToL2_revert_CustomRefund_NotSupportedInOrbit() public { + vm.expectRevert("NOT_SUPPORTED_IN_ORBIT"); + L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( + address(100), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress + ); + } + /// // Helper functions /// From 5a4a1990c30823b43abaced91b4de335612ffdac Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 5 May 2023 15:03:45 +0200 Subject: [PATCH 056/163] Add natspec --- .../ethereum/gateway/L1OrbitCustomGateway.sol | 30 ++++++++ .../ethereum/gateway/L1OrbitGatewayRouter.sol | 76 ++++++++++++++----- test-foundry/L1OrbitGatewayRouter.t.sol | 28 +++++++ 3 files changed, 116 insertions(+), 18 deletions(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol index a71b8088b1..5ac1056518 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol @@ -10,6 +10,15 @@ import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; * @notice Adds new entrypoints that have `_feeAmount` as parameter, while entrypoints without that parameter are reverted. */ contract L1OrbitCustomGateway is L1CustomGateway { + /** + * @notice Allows L1 Token contract to trustlessly register its custom L2 counterpart, in an ERC20-based rollup. Retryable costs are paid in native token. + * @param _l2Address counterpart address of L1 token + * @param _maxGas max gas for L2 retryable execution + * @param _gasPriceBid gas price for L2 retryable ticket + * @param _maxSubmissionCost base submission cost for L2 retryable ticket + * @param _feeAmount total amount of fees in native token to cover for retryable ticket costs. This amount will be transferred from user to bridge. + * @return Retryable ticket ID + */ function registerTokenToL2( address _l2Address, uint256 _maxGas, @@ -28,6 +37,16 @@ contract L1OrbitCustomGateway is L1CustomGateway { ); } + /** + * @notice Allows L1 Token contract to trustlessly register its custom L2 counterpart, in an ERC20-based rollup. Retryable costs are paid in native token. + * @param _l2Address counterpart address of L1 token + * @param _maxGas max gas for L2 retryable execution + * @param _gasPriceBid gas price for L2 retryable ticket + * @param _maxSubmissionCost base submission cost for L2 retryable ticket + * @param _creditBackAddress address for crediting back overpayment of _maxSubmissionCost + * @param _feeAmount total amount of fees in native token to cover for retryable ticket costs. This amount will be transferred from user to bridge. + * @return Retryable ticket ID + */ function registerTokenToL2( address _l2Address, uint256 _maxGas, @@ -47,6 +66,17 @@ contract L1OrbitCustomGateway is L1CustomGateway { ); } + /** + * @notice Allows owner to force register a custom L1/L2 token pair. + * @dev _l1Addresses[i] counterpart is assumed to be _l2Addresses[i] + * @param _l1Addresses array of L1 addresses + * @param _l2Addresses array of L2 addresses + * @param _maxGas max gas for L2 retryable execution + * @param _gasPriceBid gas price for L2 retryable ticket + * @param _maxSubmissionCost base submission cost for L2 retryable ticket + * @param _feeAmount total amount of fees in native token to cover for retryable ticket costs. This amount will be transferred from user to bridge. + * @return Retryable ticket ID + */ function forceRegisterTokenToL2( address[] calldata _l1Addresses, address[] calldata _l2Addresses, diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol index 292bb0505c..d4d5dba213 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol @@ -6,16 +6,25 @@ import { L1GatewayRouter } from "./L1GatewayRouter.sol"; import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; /** - * @title Handles deposits from Ethereum into L2 in ERC20-based rollups where custom token is used to pay for fees. Tokens are routed to their appropriate L1 gateway. + * @title Handles deposits from L1 into L2 in ERC20-based rollups where custom token is used to pay for fees. Tokens are routed to their appropriate L1 gateway. * @notice Router itself also conforms to the Gateway interface. Router also serves as an L1-L2 token address oracle. */ contract L1OrbitGatewayRouter is L1GatewayRouter { + /** + * @notice Allows owner to register the default gateway. + * @param newL1DefaultGateway default gateway address + * @param _maxGas max gas for L2 retryable execution + * @param _gasPriceBid gas price for L2 retryable ticket + * @param _maxSubmissionCost base submission cost for L2 retryable ticket + * @param _feeAmount total amount of fees in native token to cover for retryable ticket costs. This amount will be transferred from user to bridge. + * @return Retryable ticket ID + */ function setDefaultGateway( address newL1DefaultGateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, - uint256 feeAmount + uint256 _feeAmount ) external onlyOwner returns (uint256) { return _setDefaultGateway( @@ -23,17 +32,49 @@ contract L1OrbitGatewayRouter is L1GatewayRouter { _maxGas, _gasPriceBid, _maxSubmissionCost, - feeAmount + _feeAmount ); } + /** + * @notice Allows L1 Token contract to trustlessly register its gateway. + * @dev Other setGateway method allows excess eth recovery from _maxSubmissionCost and is recommended. + * @param _gateway l1 gateway address + * @param _maxGas max gas for L2 retryable execution + * @param _gasPriceBid gas price for L2 retryable ticket + * @param _maxSubmissionCost base submission cost for L2 retryable ticket + * @param _feeAmount total amount of fees in native token to cover for retryable ticket costs. This amount will be transferred from user to bridge. + * @return Retryable ticket ID + */ + function setGateway( + address _gateway, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + uint256 _feeAmount + ) external returns (uint256) { + return + setGateway(_gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender, _feeAmount); + } + + /** + * @notice Allows L1 Token contract to trustlessly register its gateway. + * @dev Other setGateway method allows excess eth recovery from _maxSubmissionCost and is recommended. + * @param _gateway l1 gateway address + * @param _maxGas max gas for L2 retryable execution + * @param _gasPriceBid gas price for L2 retryable ticket + * @param _maxSubmissionCost base submission cost L2 retryable tick3et + * @param _creditBackAddress address for crediting back overpayment of _maxSubmissionCost + * @param _feeAmount total amount of fees in native token to cover for retryable ticket costs. This amount will be transferred from user to bridge. + * @return Retryable ticket ID + */ function setGateway( address _gateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, address _creditBackAddress, - uint256 feeAmount + uint256 _feeAmount ) public returns (uint256) { return _setGatewayWithCreditBack( @@ -42,28 +83,27 @@ contract L1OrbitGatewayRouter is L1GatewayRouter { _gasPriceBid, _maxSubmissionCost, _creditBackAddress, - feeAmount + _feeAmount ); } - function setGateway( - address _gateway, - uint256 _maxGas, - uint256 _gasPriceBid, - uint256 _maxSubmissionCost, - uint256 feeAmount - ) external returns (uint256) { - return - setGateway(_gateway, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.sender, feeAmount); - } - + /** + * @notice Allows owner to register gateways for specific tokens. + * @param _token list of L1 token addresses + * @param _gateway list of L1 gateway addresses + * @param _maxGas max gas for L2 retryable execution + * @param _gasPriceBid gas price for L2 retryable ticket + * @param _maxSubmissionCost base submission cost for L2 retryable ticket + * @param _feeAmount total amount of fees in native token to cover for retryable ticket costs. This amount will be transferred from user to bridge. + * @return Retryable ticket ID + */ function setGateways( address[] memory _token, address[] memory _gateway, uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, - uint256 feeAmount + uint256 _feeAmount ) external payable onlyOwner returns (uint256) { return _setGateways( @@ -73,7 +113,7 @@ contract L1OrbitGatewayRouter is L1GatewayRouter { _gasPriceBid, _maxSubmissionCost, msg.sender, - feeAmount + _feeAmount ); } diff --git a/test-foundry/L1OrbitGatewayRouter.t.sol b/test-foundry/L1OrbitGatewayRouter.t.sol index c593be92a5..5d0c7f1b2e 100644 --- a/test-foundry/L1OrbitGatewayRouter.t.sol +++ b/test-foundry/L1OrbitGatewayRouter.t.sol @@ -550,6 +550,22 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); } + function test_setGateway_revert_NotSupportedInOrbit() public { + vm.expectRevert("NOT_SUPPORTED_IN_ORBIT"); + l1OrbitRouter.setGateway(address(102), maxGas, gasPriceBid, maxSubmissionCost); + } + + function test_setGateway_revert_CustomCreaditbackNotSupportedInOrbit() public { + vm.expectRevert("NOT_SUPPORTED_IN_ORBIT"); + l1OrbitRouter.setGateway( + address(103), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress + ); + } + function test_setGateway_revert_TokenNotHandledByGateway() public override { // create gateway L1OrbitCustomGateway gateway = new L1OrbitCustomGateway(); @@ -762,6 +778,18 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); } + function test_setGateways_revert_NotSupportedInOrbit() public { + vm.prank(owner); + vm.expectRevert("NOT_SUPPORTED_IN_ORBIT"); + l1OrbitRouter.setGateways( + new address[](2), + new address[](2), + maxGas, + gasPriceBid, + maxSubmissionCost + ); + } + event ERC20InboxRetryableTicket( address from, address to, From 96fa019675666ec1e481e374b3ae23f6d0a5bf5e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 5 May 2023 16:14:58 +0200 Subject: [PATCH 057/163] Add comments for missing params --- .../ethereum/gateway/L1ArbitrumGateway.sol | 2 +- .../ethereum/gateway/L1GatewayRouter.sol | 98 +++++++++---------- .../ethereum/gateway/L1OrbitCustomGateway.sol | 4 +- .../ethereum/gateway/L1OrbitERC20Gateway.sol | 2 +- 4 files changed, 53 insertions(+), 53 deletions(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol index 1c14267836..6479548c6a 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol @@ -371,7 +371,7 @@ abstract contract L1ArbitrumGateway is * @notice Intermediate internal function that passes on parameters needed to trigger creation of retryable ticket. * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2 * @param _from Initiator of deposit - * @param _amount Token of token being deposited + * @param _amount Token amount being deposited * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution * @param _gasPriceBid Gas price for L2 execution * @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee diff --git a/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol b/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol index 724379c7d0..0ebbcc504f 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol @@ -120,55 +120,6 @@ contract L1GatewayRouter is owner = newOwner; } - function _setGateways( - address[] memory _token, - address[] memory _gateway, - uint256 _maxGas, - uint256 _gasPriceBid, - uint256 _maxSubmissionCost, - address _creditBackAddress, - uint256 feeAmount - ) internal returns (uint256) { - require(_token.length == _gateway.length, "WRONG_LENGTH"); - - for (uint256 i = 0; i < _token.length; i++) { - l1TokenToGateway[_token[i]] = _gateway[i]; - emit GatewaySet(_token[i], _gateway[i]); - // overwrite memory so the L2 router receives the L2 address of each gateway - if (_gateway[i] != address(0) && _gateway[i] != DISABLED) { - // if we are assigning a gateway to the token, the address oracle of the gateway - // must return something other than the 0 address - // this check helps avoid misconfiguring gateways - require( - TokenGateway(_gateway[i]).calculateL2TokenAddress(_token[i]) != address(0), - "TOKEN_NOT_HANDLED_BY_GATEWAY" - ); - _gateway[i] = TokenGateway(_gateway[i]).counterpartGateway(); - } - } - - bytes memory data = abi.encodeWithSelector( - L2GatewayRouter.setGateway.selector, - _token, - _gateway - ); - - return - sendTxToL2( - inbox, - counterpartGateway, - _creditBackAddress, - feeAmount, - 0, - L2GasParams({ - _maxSubmissionCost: _maxSubmissionCost, - _maxGas: _maxGas, - _gasPriceBid: _gasPriceBid - }), - data - ); - } - /** * @notice Allows L1 Token contract to trustlessly register its gateway. (other setGateway method allows excess eth recovery from _maxSubmissionCost and is recommended) * @param _gateway l1 gateway address @@ -273,6 +224,55 @@ contract L1GatewayRouter is ); } + function _setGateways( + address[] memory _token, + address[] memory _gateway, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + address _creditBackAddress, + uint256 feeAmount + ) internal returns (uint256) { + require(_token.length == _gateway.length, "WRONG_LENGTH"); + + for (uint256 i = 0; i < _token.length; i++) { + l1TokenToGateway[_token[i]] = _gateway[i]; + emit GatewaySet(_token[i], _gateway[i]); + // overwrite memory so the L2 router receives the L2 address of each gateway + if (_gateway[i] != address(0) && _gateway[i] != DISABLED) { + // if we are assigning a gateway to the token, the address oracle of the gateway + // must return something other than the 0 address + // this check helps avoid misconfiguring gateways + require( + TokenGateway(_gateway[i]).calculateL2TokenAddress(_token[i]) != address(0), + "TOKEN_NOT_HANDLED_BY_GATEWAY" + ); + _gateway[i] = TokenGateway(_gateway[i]).counterpartGateway(); + } + } + + bytes memory data = abi.encodeWithSelector( + L2GatewayRouter.setGateway.selector, + _token, + _gateway + ); + + return + sendTxToL2( + inbox, + counterpartGateway, + _creditBackAddress, + feeAmount, + 0, + L2GasParams({ + _maxSubmissionCost: _maxSubmissionCost, + _maxGas: _maxGas, + _gasPriceBid: _gasPriceBid + }), + data + ); + } + function outboundTransfer( address _token, address _to, diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol index 5ac1056518..37b5488000 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol @@ -84,7 +84,7 @@ contract L1OrbitCustomGateway is L1CustomGateway { uint256 _gasPriceBid, uint256 _maxSubmissionCost, uint256 _feeAmount - ) external payable virtual onlyOwner returns (uint256) { + ) external payable onlyOwner returns (uint256) { return _forceRegisterTokenToL2( _l1Addresses, @@ -151,7 +151,7 @@ contract L1OrbitCustomGateway is L1CustomGateway { function _initiateDeposit( address _refundTo, address _from, - uint256, + uint256, // _amount, this info is already contained in _data uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index 0a94ed6392..21f09a27f3 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -29,7 +29,7 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { function _initiateDeposit( address _refundTo, address _from, - uint256, + uint256, // _amount, this info is already contained in _data uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, From 0638a2301adc03bc7803682c00bbbb9b9e6d1e7f Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 8 May 2023 15:47:50 +0200 Subject: [PATCH 058/163] Add L1ReverseCustomGateway test cases --- test-foundry/L1ArbitrumExtendedGateway.t.sol | 2 +- test-foundry/L1ReverseCustomGateway.t.sol | 240 +++++++++++++++++++ 2 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 test-foundry/L1ReverseCustomGateway.t.sol diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol index 37d320eac7..287927a4d9 100644 --- a/test-foundry/L1ArbitrumExtendedGateway.t.sol +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -38,7 +38,7 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { assertEq(encodedWithdrawal, expectedEncoding, "Invalid encodeWithdrawal"); } - function test_finalizeInboundTransfer() public { + function test_finalizeInboundTransfer() public virtual { // fund gateway with tokens being withdrawn vm.prank(address(l1Gateway)); TestERC20(address(token)).mint(); diff --git a/test-foundry/L1ReverseCustomGateway.t.sol b/test-foundry/L1ReverseCustomGateway.t.sol new file mode 100644 index 0000000000..1f4a7a4e2b --- /dev/null +++ b/test-foundry/L1ReverseCustomGateway.t.sol @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import { L1CustomGatewayTest, InboxMock, IERC20, IInbox, TestERC20 } from "./L1CustomGateway.t.sol"; +import { L1ReverseCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1ReverseCustomGateway.sol"; +import { MintableTestCustomTokenL1, ReverseTestCustomTokenL1 } from "contracts/tokenbridge/test/TestCustomTokenL1.sol"; + +contract L1ReverseCustomGatewayTest is L1CustomGatewayTest { + function setUp() public override { + inbox = address(new InboxMock()); + + l1Gateway = new L1ReverseCustomGateway(); + L1ReverseCustomGateway(address(l1Gateway)).initialize(l2Gateway, router, inbox, owner); + + token = IERC20(address(new TestERC20())); + + maxSubmissionCost = 20; + retryableCost = maxSubmissionCost + gasPriceBid * maxGas; + + // fund user and router + vm.prank(user); + TestERC20(address(token)).mint(); + vm.deal(router, 100 ether); + vm.deal(address(token), 100 ether); + vm.deal(owner, 100 ether); + } + + /* solhint-disable func-name-mixedcase */ + function test_finalizeInboundTransfer() public override { + // fund gateway with bridged tokens + MintableTestCustomTokenL1 bridgedToken = new MintableTestCustomTokenL1( + address(l1Gateway), + router + ); + vm.prank(address(l1Gateway)); + bridgedToken.mint(); + + // snapshot state before + uint256 userBalanceBefore = bridgedToken.balanceOf(user); + + // deposit params + address from = address(3000); + uint256 amount = 25; + uint256 exitNum = 7; + bytes memory callHookData = ""; + bytes memory data = abi.encode(exitNum, callHookData); + + InboxMock(address(inbox)).setL2ToL1Sender(l2Gateway); + + // trigger deposit + vm.prank(address(IInbox(l1Gateway.inbox()).bridge())); + l1Gateway.finalizeInboundTransfer(address(bridgedToken), from, user, amount, data); + + // check tokens are minted + uint256 userBalanceAfter = bridgedToken.balanceOf(user); + assertEq(userBalanceAfter - userBalanceBefore, amount, "Wrong user balance"); + } + + function test_outboundTransfer() public override { + // fund user with tokens + MintableTestCustomTokenL1 bridgedToken = new ReverseTestCustomTokenL1( + address(l1Gateway), + router + ); + vm.prank(address(user)); + bridgedToken.mint(); + + // snapshot state before + uint256 userBalanceBefore = bridgedToken.balanceOf(user); + + uint256 amount = 300; + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // register token to gateway + vm.mockCall( + address(bridgedToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.deal(address(bridgedToken), 100 ether); + vm.prank(address(bridgedToken)); + uint256 seqNum0 = L1ReverseCustomGateway(address(l1Gateway)).registerTokenToL2{ + value: retryableCost + }(makeAddr("tokenL2Address"), maxGas, gasPriceBid, maxSubmissionCost, creditBackAddress); + + // approve token + vm.prank(user); + bridgedToken.approve(address(l1Gateway), amount); + + // 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(address(bridgedToken), user, user, amount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(bridgedToken), user, user, 1, amount); + + // trigger transfer + vm.prank(router); + bytes memory seqNum1 = l1Gateway.outboundTransfer{ value: retryableCost }( + address(bridgedToken), + user, + amount, + maxGas, + gasPriceBid, + routerEncodedData + ); + + // check tokens are burned + uint256 userBalanceAfter = bridgedToken.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, amount, "Wrong user balance"); + + assertEq(seqNum0, 0, "Invalid seqNum0"); + assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); + } + + function test_outboundTransferCustomRefund() public override { + // fund user with tokens + MintableTestCustomTokenL1 bridgedToken = new ReverseTestCustomTokenL1( + address(l1Gateway), + router + ); + vm.prank(address(user)); + bridgedToken.mint(); + + // snapshot state before + uint256 userBalanceBefore = bridgedToken.balanceOf(user); + + uint256 amount = 450; + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // register token to gateway + vm.mockCall( + address(bridgedToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.deal(address(bridgedToken), 100 ether); + vm.prank(address(bridgedToken)); + uint256 seqNum0 = L1ReverseCustomGateway(address(l1Gateway)).registerTokenToL2{ + value: retryableCost + }(makeAddr("tokenL2Address"), maxGas, gasPriceBid, maxSubmissionCost, creditBackAddress); + + // approve token + vm.prank(user); + bridgedToken.approve(address(l1Gateway), amount); + + // 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(address(bridgedToken), user, user, amount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(bridgedToken), user, user, 1, amount); + + // trigger deposit + vm.prank(router); + bytes memory seqNum1 = l1Gateway.outboundTransferCustomRefund{ value: retryableCost }( + address(bridgedToken), + creditBackAddress, + user, + amount, + maxGas, + gasPriceBid, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = bridgedToken.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, amount, "Wrong user balance"); + + assertEq(seqNum0, 0, "Invalid seqNum0"); + assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); + } + + function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public override { + // fund user with tokens + MintableTestCustomTokenL1 bridgedToken = new ReverseTestCustomTokenL1( + address(l1Gateway), + router + ); + vm.prank(address(user)); + bridgedToken.mint(); + + uint256 tooManyTokens = 500 ether; + + // register token to gateway + vm.mockCall( + address(bridgedToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.deal(address(bridgedToken), 100 ether); + vm.prank(address(bridgedToken)); + L1ReverseCustomGateway(address(l1Gateway)).registerTokenToL2{ value: retryableCost }( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + makeAddr("creditBackAddress") + ); + + vm.prank(router); + vm.expectRevert("ERC20: burn amount exceeds balance"); + l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + address(bridgedToken), + user, + user, + tooManyTokens, + 0.1 ether, + 0.01 ether, + buildRouterEncodedData("") + ); + } +} From bd9250deb5bf378ab6602fcb2995797e9ff07c6e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 8 May 2023 16:45:26 +0200 Subject: [PATCH 059/163] Implement and test L1OrbitReverseCustomGateway --- .../gateway/L1OrbitReverseCustomGateway.sol | 39 +++ test-foundry/L1OrbitCustomGateway.t.sol | 8 +- .../L1OrbitReverseCustomGateway.t.sol | 263 ++++++++++++++++++ test-foundry/L1ReverseCustomGateway.t.sol | 2 +- 4 files changed, 307 insertions(+), 5 deletions(-) create mode 100644 contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol create mode 100644 test-foundry/L1OrbitReverseCustomGateway.t.sol diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol new file mode 100644 index 0000000000..f875946c3c --- /dev/null +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import { L1OrbitCustomGateway } from "./L1OrbitCustomGateway.sol"; +import { IArbToken } from "../../arbitrum/IArbToken.sol"; + +/** + * @title L1 Gateway for reverse "custom" bridging functionality in an ERC20-based rollup. + * @notice Handles some (but not all!) reverse custom Gateway needs. + * Use the reverse custom gateway instead of the normal custom + * gateway if you want total supply to be tracked on the L2 + * rather than the L1. + * @dev The reverse custom gateway burns on the l2 and escrows on the l1 + * which is the opposite of the way the normal custom gateway works + * This means that the total supply L2 isn't affected by briding, which + * is helpful for observers calculating the total supply especially if + * if minting is also occuring on L2 + */ +contract L1OrbitReverseCustomGateway is L1OrbitCustomGateway { + function inboundEscrowTransfer( + address _l1Address, + address _dest, + uint256 _amount + ) internal virtual override { + IArbToken(_l1Address).bridgeMint(_dest, _amount); + } + + function outboundEscrowTransfer( + address _l1Token, + address _from, + uint256 _amount + ) internal override returns (uint256) { + IArbToken(_l1Token).bridgeBurn(_from, _amount); + // by default we assume that the amount we send to bridgeBurn is the amount burnt + // this might not be the case for every token + return _amount; + } +} diff --git a/test-foundry/L1OrbitCustomGateway.t.sol b/test-foundry/L1OrbitCustomGateway.t.sol index 1779e46403..311a066fd4 100644 --- a/test-foundry/L1OrbitCustomGateway.t.sol +++ b/test-foundry/L1OrbitCustomGateway.t.sol @@ -11,7 +11,7 @@ import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { uint256 public nativeTokenTotalFee; - function setUp() public override { + function setUp() public virtual override { inbox = address(new ERC20InboxMock()); l1Gateway = new L1OrbitCustomGateway(); @@ -139,7 +139,7 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { ); } - function test_outboundTransfer() public override { + function test_outboundTransfer() public virtual override { // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); @@ -215,7 +215,7 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); } - function test_outboundTransferCustomRefund() public override { + function test_outboundTransferCustomRefund() public virtual override { // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); uint256 l1GatewayBalanceBefore = token.balanceOf(address(l1Gateway)); @@ -292,7 +292,7 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); } - function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public override { + function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public virtual override { uint256 tooManyTokens = 500 ether; // register token to gateway diff --git a/test-foundry/L1OrbitReverseCustomGateway.t.sol b/test-foundry/L1OrbitReverseCustomGateway.t.sol new file mode 100644 index 0000000000..d8976b6441 --- /dev/null +++ b/test-foundry/L1OrbitReverseCustomGateway.t.sol @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import { L1OrbitCustomGatewayTest, ERC20InboxMock, TestERC20, IERC20 } from "./L1OrbitCustomGateway.t.sol"; +import { L1OrbitReverseCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol"; +import { MintableTestCustomTokenL1, ReverseTestCustomTokenL1 } from "contracts/tokenbridge/test/TestCustomTokenL1.sol"; +import { IInbox } from "contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol"; + +contract L1OrbitReverseCustomGatewayTest is L1OrbitCustomGatewayTest { + function setUp() public override { + inbox = address(new ERC20InboxMock()); + + l1Gateway = new L1OrbitReverseCustomGateway(); + L1OrbitReverseCustomGateway(address(l1Gateway)).initialize(l2Gateway, router, inbox, owner); + + token = IERC20(address(new TestERC20())); + + maxSubmissionCost = 0; + nativeTokenTotalFee = maxGas * gasPriceBid; + + // fund user and router + vm.prank(user); + TestERC20(address(token)).mint(); + vm.deal(router, 100 ether); + vm.deal(address(token), 100 ether); + vm.deal(owner, 100 ether); + } + + /* solhint-disable func-name-mixedcase */ + function test_finalizeInboundTransfer() public override { + // fund gateway with bridged tokens + MintableTestCustomTokenL1 bridgedToken = new MintableTestCustomTokenL1( + address(l1Gateway), + router + ); + vm.prank(address(l1Gateway)); + bridgedToken.mint(); + + // snapshot state before + uint256 userBalanceBefore = bridgedToken.balanceOf(user); + + // deposit params + address from = address(3000); + uint256 amount = 25; + uint256 exitNum = 7; + bytes memory callHookData = ""; + bytes memory data = abi.encode(exitNum, callHookData); + + ERC20InboxMock(address(inbox)).setL2ToL1Sender(l2Gateway); + + // trigger deposit + vm.prank(address(IInbox(l1Gateway.inbox()).bridge())); + L1OrbitReverseCustomGateway(address(l1Gateway)).finalizeInboundTransfer( + address(bridgedToken), + from, + user, + amount, + data + ); + + // check tokens are minted + uint256 userBalanceAfter = bridgedToken.balanceOf(user); + assertEq(userBalanceAfter - userBalanceBefore, amount, "Wrong user balance"); + } + + function test_outboundTransfer() public override { + // fund user with tokens + MintableTestCustomTokenL1 bridgedToken = new ReverseTestCustomTokenL1( + address(l1Gateway), + router + ); + vm.prank(address(user)); + bridgedToken.mint(); + + // snapshot state before + uint256 userBalanceBefore = bridgedToken.balanceOf(user); + + uint256 amount = 300; + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // register token to gateway + vm.mockCall( + address(bridgedToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.deal(address(bridgedToken), 100 ether); + vm.prank(address(bridgedToken)); + uint256 seqNum0 = L1OrbitReverseCustomGateway(address(l1Gateway)).registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + // approve token + vm.prank(user); + bridgedToken.approve(address(l1Gateway), amount); + + // 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(address(bridgedToken), user, user, amount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(bridgedToken), user, user, 1, amount); + + // trigger transfer + vm.prank(router); + bytes memory seqNum1 = L1OrbitReverseCustomGateway(address(l1Gateway)).outboundTransfer( + address(bridgedToken), + user, + amount, + maxGas, + gasPriceBid, + routerEncodedData + ); + + // check tokens are burned + uint256 userBalanceAfter = bridgedToken.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, amount, "Wrong user balance"); + + assertEq(seqNum0, 0, "Invalid seqNum0"); + assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); + } + + function test_outboundTransferCustomRefund() public override { + // fund user with tokens + MintableTestCustomTokenL1 bridgedToken = new ReverseTestCustomTokenL1( + address(l1Gateway), + router + ); + vm.prank(address(user)); + bridgedToken.mint(); + + // snapshot state before + uint256 userBalanceBefore = bridgedToken.balanceOf(user); + + uint256 amount = 450; + bytes memory callHookData = ""; + bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + + // register token to gateway + vm.mockCall( + address(bridgedToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.deal(address(bridgedToken), 100 ether); + vm.prank(address(bridgedToken)); + uint256 seqNum0 = L1OrbitReverseCustomGateway(address(l1Gateway)).registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + creditBackAddress, + nativeTokenTotalFee + ); + + // approve token + vm.prank(user); + bridgedToken.approve(address(l1Gateway), amount); + + // 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(address(bridgedToken), user, user, amount, callHookData) + ); + + vm.expectEmit(true, true, true, true); + emit DepositInitiated(address(bridgedToken), user, user, 1, amount); + + // trigger deposit + vm.prank(router); + bytes memory seqNum1 = L1OrbitReverseCustomGateway(address(l1Gateway)) + .outboundTransferCustomRefund( + address(bridgedToken), + creditBackAddress, + user, + amount, + maxGas, + gasPriceBid, + routerEncodedData + ); + + // check tokens are escrowed + uint256 userBalanceAfter = bridgedToken.balanceOf(user); + assertEq(userBalanceBefore - userBalanceAfter, amount, "Wrong user balance"); + + assertEq(seqNum0, 0, "Invalid seqNum0"); + assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); + } + + function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public override { + // fund user with tokens + MintableTestCustomTokenL1 bridgedToken = new ReverseTestCustomTokenL1( + address(l1Gateway), + router + ); + vm.prank(address(user)); + bridgedToken.mint(); + + uint256 tooManyTokens = 500 ether; + + // register token to gateway + vm.mockCall( + address(bridgedToken), + abi.encodeWithSignature("isArbitrumEnabled()"), + abi.encode(uint8(0xb1)) + ); + vm.deal(address(bridgedToken), 100 ether); + vm.prank(address(bridgedToken)); + L1OrbitReverseCustomGateway(address(l1Gateway)).registerTokenToL2( + makeAddr("tokenL2Address"), + maxGas, + gasPriceBid, + maxSubmissionCost, + makeAddr("creditBackAddress"), + nativeTokenTotalFee + ); + + vm.prank(router); + vm.expectRevert("ERC20: burn amount exceeds balance"); + l1Gateway.outboundTransferCustomRefund( + address(bridgedToken), + user, + user, + tooManyTokens, + 0.1 ether, + 0.01 ether, + buildRouterEncodedData("") + ); + } +} diff --git a/test-foundry/L1ReverseCustomGateway.t.sol b/test-foundry/L1ReverseCustomGateway.t.sol index 1f4a7a4e2b..30dce5bba1 100644 --- a/test-foundry/L1ReverseCustomGateway.t.sol +++ b/test-foundry/L1ReverseCustomGateway.t.sol @@ -7,7 +7,7 @@ import { L1ReverseCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L import { MintableTestCustomTokenL1, ReverseTestCustomTokenL1 } from "contracts/tokenbridge/test/TestCustomTokenL1.sol"; contract L1ReverseCustomGatewayTest is L1CustomGatewayTest { - function setUp() public override { + function setUp() public virtual override { inbox = address(new InboxMock()); l1Gateway = new L1ReverseCustomGateway(); From 64cfba62f6dc1ce3b89869db341956f298810299 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 10 May 2023 11:13:51 +0200 Subject: [PATCH 060/163] Revert if token being deposited is native fee token --- .../ethereum/gateway/L1ERC20Gateway.sol | 2 +- .../ethereum/gateway/L1OrbitERC20Gateway.sol | 38 +++++++++++ contracts/tokenbridge/test/InboxMock.sol | 2 + test-foundry/L1OrbitERC20Gateway.t.sol | 26 ++++++++ test-foundry/L1OrbitGatewayRouter.t.sol | 64 +++++++++++++++++++ 5 files changed, 131 insertions(+), 1 deletion(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol index 6c4647cb95..245ce3e185 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol @@ -62,7 +62,7 @@ contract L1ERC20Gateway is L1ArbitrumExtendedGateway { uint256 _maxGas, uint256 _gasPriceBid, bytes calldata _data - ) public payable override nonReentrant returns (bytes memory res) { + ) public payable virtual override nonReentrant returns (bytes memory res) { return super.outboundTransferCustomRefund( _l1Token, diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index 21f09a27f3..3845f64529 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -12,6 +12,29 @@ import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; * Messages to layer 2 use the inbox's createRetryableTicket method. */ contract L1OrbitERC20Gateway is L1ERC20Gateway { + function outboundTransferCustomRefund( + address _l1Token, + address _refundTo, + address _to, + uint256 _amount, + uint256 _maxGas, + uint256 _gasPriceBid, + bytes calldata _data + ) public payable override returns (bytes memory res) { + require(_l1Token != _getNativeFeeToken(), "NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); + + return + super.outboundTransferCustomRefund( + _l1Token, + _refundTo, + _to, + _amount, + _maxGas, + _gasPriceBid, + _data + ); + } + function _parseUserEncodedData( bytes memory data ) @@ -78,4 +101,19 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { _data ); } + + /** + * @notice get rollup's native token that's used to pay for fees + */ + function _getNativeFeeToken() internal returns (address) { + address bridge = address(getBridge(inbox)); + return IERC20Bridge(bridge).nativeToken(); + } +} + +interface IERC20Bridge { + /** + * @dev token that is escrowed in bridge on L1 side and minted on L2 as native currency. Also fees are paid in this token. + */ + function nativeToken() external returns (address); } diff --git a/contracts/tokenbridge/test/InboxMock.sol b/contracts/tokenbridge/test/InboxMock.sol index bb684b003a..fac0f9454b 100644 --- a/contracts/tokenbridge/test/InboxMock.sol +++ b/contracts/tokenbridge/test/InboxMock.sol @@ -68,6 +68,8 @@ contract InboxMock is AbsInboxMock { } contract ERC20InboxMock is AbsInboxMock { + address public nativeToken = address(50000); + event ERC20InboxRetryableTicket( address from, address to, diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index 0b83d9ccf3..bfc2557c9f 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -103,6 +103,15 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { ); } + function test_outboundTransfer_revert_NotAllowedToBridgeFeeToken() public { + address nativeFeeToken = address(50000); + + // trigger deposit + vm.prank(router); + vm.expectRevert("NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); + l1Gateway.outboundTransfer(nativeFeeToken, user, 100, maxGas, gasPriceBid, ""); + } + function test_outboundTransferCustomRefund() public override { // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); @@ -162,6 +171,23 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { ); } + function test_outboundTransferCustomRefund_revert_NotAllowedToBridgeFeeToken() public { + address nativeFeeToken = address(50000); + + // trigger deposit + vm.prank(router); + vm.expectRevert("NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); + l1Gateway.outboundTransferCustomRefund( + nativeFeeToken, + creditBackAddress, + user, + 100, + maxGas, + gasPriceBid, + "" + ); + } + //// // Helper functions //// diff --git a/test-foundry/L1OrbitGatewayRouter.t.sol b/test-foundry/L1OrbitGatewayRouter.t.sol index 5d0c7f1b2e..599502f3a7 100644 --- a/test-foundry/L1OrbitGatewayRouter.t.sol +++ b/test-foundry/L1OrbitGatewayRouter.t.sol @@ -133,6 +133,34 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); } + function test_outboundTransfer_revert_NotAllowedToBridgeFeeToken() public { + address nativeFeeToken = address(50000); + + // init default gateway + L1OrbitERC20Gateway(defaultGateway).initialize( + makeAddr("defaultGatewayCounterpart"), + address(l1Router), + inbox, + 0x0000000000000000000000000000000000000000000000000000000000000001, + makeAddr("l2BeaconProxyFactory") + ); + + // set default gateway + vm.prank(owner); + l1OrbitRouter.setDefaultGateway( + address(defaultGateway), + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + /// deposit it + vm.prank(user); + vm.expectRevert("NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); + l1Router.outboundTransfer(nativeFeeToken, user, 100, maxGas, gasPriceBid, ""); + } + function test_outboundTransferCustomRefund() public override { // init default gateway L1OrbitERC20Gateway(defaultGateway).initialize( @@ -197,6 +225,42 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); } + function test_outboundTransferCustomRefund_revert_NotAllowedToBridgeFeeToken() public { + address nativeFeeToken = address(50000); + + // init default gateway + L1OrbitERC20Gateway(defaultGateway).initialize( + makeAddr("defaultGatewayCounterpart"), + address(l1Router), + inbox, + 0x0000000000000000000000000000000000000000000000000000000000000001, + makeAddr("l2BeaconProxyFactory") + ); + + // set default gateway + vm.prank(owner); + l1OrbitRouter.setDefaultGateway( + address(defaultGateway), + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + + /// deposit it + vm.prank(user); + vm.expectRevert("NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); + l1Router.outboundTransferCustomRefund( + nativeFeeToken, + user, + user, + 100, + maxGas, + gasPriceBid, + "" + ); + } + function test_setDefaultGateway() public override { L1OrbitERC20Gateway newL1DefaultGateway = new L1OrbitERC20Gateway(); address newDefaultGatewayCounterpart = makeAddr("newDefaultGatewayCounterpart"); From 571eeadd0c35fe4d0d564b74758d85ffee8ad566 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 11 May 2023 12:41:10 +0200 Subject: [PATCH 061/163] Add script for connecting to local network --- package.json | 2 + scripts/genTokenBridge.ts | 17 +++++ scripts/testSetup.ts | 134 ++++++++++++++++++++++++++++++++++++++ yarn.lock | 18 +++-- 4 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 scripts/genTokenBridge.ts create mode 100644 scripts/testSetup.ts diff --git a/package.json b/package.json index d71563f1f4..20165710ef 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "test:l2": "hardhat test test/*.l2.ts", "test:unit": "forge test", "test:storage": "./scripts/storage_layout_test.bash", + "test:deploy:tokenbridge": "ts-node ./scripts/genTokenBridge.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", @@ -37,6 +38,7 @@ "@openzeppelin/contracts-upgradeable": "^4.8.3" }, "devDependencies": { + "@arbitrum/sdk": "^3.1.3", "@nomiclabs/hardhat-ethers": "^2.0.1", "@nomiclabs/hardhat-etherscan": "^3.1.0", "@nomiclabs/hardhat-waffle": "^2.0.1", diff --git a/scripts/genTokenBridge.ts b/scripts/genTokenBridge.ts new file mode 100644 index 0000000000..992e45971a --- /dev/null +++ b/scripts/genTokenBridge.ts @@ -0,0 +1,17 @@ +import { setupNetworks, config } from './testSetup' +import * as fs from 'fs' + +async function main() { + const { l1Network, l2Network } = await setupNetworks( + config.ethUrl, + config.arbUrl + ) + + fs.writeFileSync( + './files/local/network.json', + JSON.stringify({ l1Network, l2Network }, null, 2) + ) + console.log('network.json updated') +} + +main().then(() => console.log('Done.')) diff --git a/scripts/testSetup.ts b/scripts/testSetup.ts new file mode 100644 index 0000000000..88f193dd8e --- /dev/null +++ b/scripts/testSetup.ts @@ -0,0 +1,134 @@ +import { JsonRpcProvider } from '@ethersproject/providers' +import dotenv from 'dotenv' +import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' +import { execSync } from 'child_process' +import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' +import { Signer } from 'ethers' + +dotenv.config() + +export const config = { + arbUrl: process.env['ARB_URL'] as string, + ethUrl: process.env['ETH_URL'] as string, +} + +export const getCustomNetworks = async ( + l1Url: string, + l2Url: string +): Promise<{ + l1Network: L1Network + l2Network: Omit & { nativeToken: string } +}> => { + const l1Provider = new JsonRpcProvider(l1Url) + const l2Provider = new JsonRpcProvider(l2Url) + let deploymentData: string + try { + deploymentData = execSync( + 'docker exec nitro_sequencer_1 cat /config/deployment.json' + ).toString() + } catch (e) { + deploymentData = execSync( + 'docker exec nitro-sequencer-1 cat /config/deployment.json' + ).toString() + } + const parsedDeploymentData = JSON.parse(deploymentData) as { + bridge: string + inbox: string + ['sequencer-inbox']: string + rollup: string + ['native-erc20-token']: string + } + + const rollup = RollupAdminLogic__factory.connect( + parsedDeploymentData.rollup, + l1Provider + ) + const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() + + const bridge = Bridge__factory.connect( + parsedDeploymentData.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 & { nativeToken: string } = { + chainID: l2NetworkInfo.chainId, + confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), + ethBridge: { + bridge: parsedDeploymentData.bridge, + inbox: parsedDeploymentData.inbox, + outbox: outboxAddr, + rollup: parsedDeploymentData.rollup, + sequencerInbox: parsedDeploymentData['sequencer-inbox'], + }, + nativeToken: parsedDeploymentData['native-erc20-token'], + explorerUrl: '', + isArbitrum: true, + isCustom: true, + name: 'ArbLocal', + partnerChainID: l1NetworkInfo.chainId, + retryableLifetimeSeconds: 7 * 24 * 60 * 60, + nitroGenesisBlock: 0, + nitroGenesisL1Block: 0, + depositTimeout: 900000, + } + return { + l1Network, + l2Network, + } +} + +export const setupNetworks = async (l1Url: string, l2Url: string) => { + const { l1Network, l2Network: coreL2Network } = await getCustomNetworks( + l1Url, + l2Url + ) + const l2Network: L2Network & { nativeToken: string } = { + ...coreL2Network, + tokenBridge: { + l1CustomGateway: '', + l1ERC20Gateway: '', + l1GatewayRouter: '', + l1MultiCall: '', + l1ProxyAdmin: '', + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: '', + l2ERC20Gateway: '', + l2GatewayRouter: '', + l2Multicall: '', + l2ProxyAdmin: '', + l2Weth: '', + l2WethGateway: '', + }, + } + + addCustomNetwork({ + customL1Network: l1Network, + customL2Network: l2Network, + }) + + return { + l1Network, + l2Network, + } +} + +export function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)) +} diff --git a/yarn.lock b/yarn.lock index 5eef3e8328..391641d835 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16,6 +16,16 @@ "@openzeppelin/contracts-upgradeable" "4.5.2" hardhat "^2.6.6" +"@arbitrum/sdk@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.3.tgz#75236043717a450b569faaa087687c51d525b0c3" + integrity sha512-Dn1or7/Guc3dItuiiWaoYQ37aCDwiWTZGPIrg4yBJW27BgiDGbo0mjPDAhKTh4p5NDOWyE8bZ0vZai86COZIUA== + dependencies: + "@ethersproject/address" "^5.0.8" + "@ethersproject/bignumber" "^5.1.1" + "@ethersproject/bytes" "^5.0.8" + ethers "^5.1.0" + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -258,7 +268,7 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.8", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -284,7 +294,7 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.1.1", "@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== @@ -293,7 +303,7 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.8", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== @@ -4861,7 +4871,7 @@ ethers@^5.0.1, ethers@^5.0.2, ethers@^5.4.5, ethers@^5.5.2: "@ethersproject/web" "5.7.1" "@ethersproject/wordlists" "5.7.0" -ethers@^5.7.2: +ethers@^5.1.0, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== From 03fecc04c11d4725fc7c9a2b9f893e34223fb326 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 18 May 2023 18:44:34 +0200 Subject: [PATCH 062/163] Add native token transfers from user to the inbox --- .../ethereum/gateway/L1OrbitCustomGateway.sol | 13 +++++++++++++ .../ethereum/gateway/L1OrbitERC20Gateway.sol | 18 +++++++++++------- .../ethereum/gateway/L1OrbitGatewayRouter.sol | 12 ++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol index 37b5488000..7d6bc02f57 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol @@ -4,12 +4,17 @@ pragma solidity ^0.8.0; import { L1CustomGateway } from "./L1CustomGateway.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 Gateway for "custom" bridging functionality in an ERC20-based rollup. * @notice Adds new entrypoints that have `_feeAmount` as parameter, while entrypoints without that parameter are reverted. */ contract L1OrbitCustomGateway is L1CustomGateway { + using SafeERC20 for IERC20; + /** * @notice Allows L1 Token contract to trustlessly register its custom L2 counterpart, in an ERC20-based rollup. Retryable costs are paid in native token. * @param _l2Address counterpart address of L1 token @@ -187,6 +192,14 @@ contract L1OrbitCustomGateway is L1CustomGateway { uint256 _gasPriceBid, bytes memory _data ) internal override returns (uint256) { + { + // Transfer native token amount needed to pay for retryable fees to the inbox. + // Tokens are transferred from `_user` - that's the msg.sender account in the router's context. + address bridge = address(getBridge(_inbox)); + address nativeFeeToken = IERC20Bridge(bridge).nativeToken(); + IERC20(nativeFeeToken).safeTransferFrom(_user, _inbox, _totalFeeAmount); + } + return IERC20Inbox(_inbox).createRetryableTicket( _to, diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index 3845f64529..2776f389fc 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -4,6 +4,8 @@ pragma solidity ^0.8.0; import { L1ERC20Gateway, IERC20 } from "./L1ERC20Gateway.sol"; import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { IERC20Bridge } from "../../libraries/IERC20Bridge.sol"; /** * @title Layer 1 Gateway contract for bridging standard ERC20s in ERC20-based rollup @@ -12,6 +14,8 @@ import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; * Messages to layer 2 use the inbox's createRetryableTicket method. */ contract L1OrbitERC20Gateway is L1ERC20Gateway { + using SafeERC20 for IERC20; + function outboundTransferCustomRefund( address _l1Token, address _refundTo, @@ -88,6 +92,13 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { uint256 _gasPriceBid, bytes memory _data ) internal override returns (uint256) { + { + // Transfer native token amount needed to pay for retryable fees to the inbox. + // Tokens are transferred from `_user` - that's the msg.sender account in the router's context. + address nativeFeeToken = _getNativeFeeToken(); + IERC20(nativeFeeToken).safeTransferFrom(_user, _inbox, _totalFeeAmount); + } + return IERC20Inbox(_inbox).createRetryableTicket( _to, @@ -110,10 +121,3 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { return IERC20Bridge(bridge).nativeToken(); } } - -interface IERC20Bridge { - /** - * @dev token that is escrowed in bridge on L1 side and minted on L2 as native currency. Also fees are paid in this token. - */ - function nativeToken() external returns (address); -} diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol index d4d5dba213..20bbba601d 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol @@ -4,12 +4,17 @@ pragma solidity ^0.8.0; import { L1GatewayRouter } from "./L1GatewayRouter.sol"; import { IERC20Inbox } from "../L1ArbitrumMessenger.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import { IERC20Bridge } from "../../libraries/IERC20Bridge.sol"; /** * @title Handles deposits from L1 into L2 in ERC20-based rollups where custom token is used to pay for fees. Tokens are routed to their appropriate L1 gateway. * @notice Router itself also conforms to the Gateway interface. Router also serves as an L1-L2 token address oracle. */ contract L1OrbitGatewayRouter is L1GatewayRouter { + using SafeERC20 for IERC20; + /** * @notice Allows owner to register the default gateway. * @param newL1DefaultGateway default gateway address @@ -129,6 +134,13 @@ contract L1OrbitGatewayRouter is L1GatewayRouter { uint256 _gasPriceBid, bytes memory _data ) internal override returns (uint256) { + { + // Transfer native token amount needed to pay fees to the inbox + address bridge = address(getBridge(_inbox)); + address nativeFeeToken = IERC20Bridge(bridge).nativeToken(); + IERC20(nativeFeeToken).safeTransferFrom(msg.sender, _inbox, _totalFeeAmount); + } + return IERC20Inbox(_inbox).createRetryableTicket( _to, From 40c2d7a3c250126e72199b391c6fbc759afc9348 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 19 May 2023 12:43:26 +0200 Subject: [PATCH 063/163] Refactor native token flow --- .../ethereum/gateway/L1OrbitCustomGateway.sol | 16 +- .../ethereum/gateway/L1OrbitERC20Gateway.sol | 13 +- .../ethereum/gateway/L1OrbitGatewayRouter.sol | 12 +- .../tokenbridge/libraries/IERC20Bridge.sol | 11 ++ contracts/tokenbridge/test/InboxMock.sol | 14 +- test-foundry/L1OrbitCustomGateway.t.sol | 86 ++++++++-- test-foundry/L1OrbitERC20Gateway.t.sol | 23 ++- test-foundry/L1OrbitGatewayRouter.t.sol | 153 ++++++++++++++++-- .../L1OrbitReverseCustomGateway.t.sol | 43 ++++- 9 files changed, 325 insertions(+), 46 deletions(-) create mode 100644 contracts/tokenbridge/libraries/IERC20Bridge.sol diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol index 7d6bc02f57..9bd4623e84 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol @@ -194,10 +194,18 @@ contract L1OrbitCustomGateway is L1CustomGateway { ) internal override returns (uint256) { { // Transfer native token amount needed to pay for retryable fees to the inbox. - // Tokens are transferred from `_user` - that's the msg.sender account in the router's context. - address bridge = address(getBridge(_inbox)); - address nativeFeeToken = IERC20Bridge(bridge).nativeToken(); - IERC20(nativeFeeToken).safeTransferFrom(_user, _inbox, _totalFeeAmount); + // 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 = msg.sender == router ? _user : msg.sender; + IERC20(nativeFeeToken).safeTransferFrom( + transferFrom, + _inbox, + _totalFeeAmount - inboxNativeTokenBalance + ); + } } return diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index 2776f389fc..5724dba3a7 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -94,9 +94,18 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { ) internal override returns (uint256) { { // Transfer native token amount needed to pay for retryable fees to the inbox. - // Tokens are transferred from `_user` - that's the msg.sender account in the router's context. + // 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 = _getNativeFeeToken(); - IERC20(nativeFeeToken).safeTransferFrom(_user, _inbox, _totalFeeAmount); + uint256 inboxNativeTokenBalance = IERC20(nativeFeeToken).balanceOf(_inbox); + if (inboxNativeTokenBalance < _totalFeeAmount) { + address transferFrom = msg.sender == router ? _user : msg.sender; + IERC20(nativeFeeToken).safeTransferFrom( + transferFrom, + _inbox, + _totalFeeAmount - inboxNativeTokenBalance + ); + } } return diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol index 20bbba601d..a98797cf31 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol @@ -135,10 +135,14 @@ contract L1OrbitGatewayRouter is L1GatewayRouter { bytes memory _data ) internal override returns (uint256) { { - // Transfer native token amount needed to pay fees to the inbox - address bridge = address(getBridge(_inbox)); - address nativeFeeToken = IERC20Bridge(bridge).nativeToken(); - IERC20(nativeFeeToken).safeTransferFrom(msg.sender, _inbox, _totalFeeAmount); + // Transfer native token amount needed to pay for retryable fees to the inbox. + // Fee tokens will be transferred from msg.sender + address nativeFeeToken = IERC20Bridge(address(getBridge(_inbox))).nativeToken(); + uint256 inboxNativeTokenBalance = IERC20(nativeFeeToken).balanceOf(_inbox); + if (inboxNativeTokenBalance < _totalFeeAmount) { + uint256 diff = _totalFeeAmount - inboxNativeTokenBalance; + IERC20(nativeFeeToken).safeTransferFrom(msg.sender, _inbox, diff); + } } return diff --git a/contracts/tokenbridge/libraries/IERC20Bridge.sol b/contracts/tokenbridge/libraries/IERC20Bridge.sol new file mode 100644 index 0000000000..6a093d74d2 --- /dev/null +++ b/contracts/tokenbridge/libraries/IERC20Bridge.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: Apache-2.0 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.6.9 <0.9.0; + +interface IERC20Bridge { + /** + * @dev token that is escrowed in bridge on L1 side and minted on L2 as native currency. Also fees are paid in this token. + */ + function nativeToken() external returns (address); +} diff --git a/contracts/tokenbridge/test/InboxMock.sol b/contracts/tokenbridge/test/InboxMock.sol index fac0f9454b..7113840f92 100644 --- a/contracts/tokenbridge/test/InboxMock.sol +++ b/contracts/tokenbridge/test/InboxMock.sol @@ -20,6 +20,7 @@ pragma solidity ^0.8.0; import "@arbitrum/nitro-contracts/src/bridge/IOutbox.sol"; import "@arbitrum/nitro-contracts/src/bridge/IBridge.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; abstract contract AbsInboxMock { address public l2ToL1SenderMock = address(0); @@ -68,7 +69,7 @@ contract InboxMock is AbsInboxMock { } contract ERC20InboxMock is AbsInboxMock { - address public nativeToken = address(50000); + address public nativeToken; event ERC20InboxRetryableTicket( address from, @@ -107,6 +108,17 @@ contract ERC20InboxMock is AbsInboxMock { tokenTotalFeeAmount, data ); + + // transfer out received native tokens (to simulate bridge spending those funds) + uint256 balance = IERC20(address(nativeToken)).balanceOf(address(this)); + if (balance > 0) { + IERC20(address(nativeToken)).transfer(address(1), balance); + } + return seqNum++; } + + function setMockNativeToken(address _nativeToken) external { + nativeToken = _nativeToken; + } } diff --git a/test-foundry/L1OrbitCustomGateway.t.sol b/test-foundry/L1OrbitCustomGateway.t.sol index 311a066fd4..65e09c298d 100644 --- a/test-foundry/L1OrbitCustomGateway.t.sol +++ b/test-foundry/L1OrbitCustomGateway.t.sol @@ -4,15 +4,21 @@ pragma solidity ^0.8.0; import { L1CustomGatewayTest, IERC20, L2CustomGateway } from "./L1CustomGateway.t.sol"; import { L1OrbitCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol"; - +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20PresetMinterPauser } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { + ERC20 public nativeToken; uint256 public nativeTokenTotalFee; function setUp() public virtual override { inbox = address(new ERC20InboxMock()); + 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)); l1Gateway = new L1OrbitCustomGateway(); L1OrbitCustomGateway(address(l1Gateway)).initialize(l2Gateway, router, inbox, owner); @@ -32,9 +38,19 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { /* solhint-disable func-name-mixedcase */ function test_calculateL2TokenAddress(address l1Token, address l2Token) public override { - vm.assume(l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS); + vm.assume( + l1Token != FOUNDRY_CHEATCODE_ADDRESS && + l2Token != FOUNDRY_CHEATCODE_ADDRESS && + l1Token != address(0) && + l1Token != router + ); vm.deal(l1Token, 100 ether); + // approve fees + ERC20PresetMinterPauser(address(nativeToken)).mint(address(l1Token), nativeTokenTotalFee); + vm.prank(address(l1Token)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // register token to gateway vm.mockCall( address(l1Token), @@ -47,7 +63,7 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { maxGas, gasPriceBid, maxSubmissionCost, - makeAddr("creditBackAddress"), + creditBackAddress, nativeTokenTotalFee ); @@ -62,6 +78,10 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { l2Tokens[0] = makeAddr("l2Token1"); l2Tokens[1] = makeAddr("l2Token2"); + // approve fees + vm.prank(owner); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // expect events vm.expectEmit(true, true, true, true); emit TokenSet(l1Tokens[0], l2Tokens[0]); @@ -149,6 +169,10 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { bytes memory routerEncodedData = buildRouterEncodedData(callHookData); // register token to gateway + ERC20PresetMinterPauser(address(nativeToken)).mint(address(token), nativeTokenTotalFee); + vm.prank(address(token)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + vm.mockCall( address(token), abi.encodeWithSignature("isArbitrumEnabled()"), @@ -168,6 +192,10 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { vm.prank(user); token.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); @@ -225,6 +253,10 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { bytes memory routerEncodedData = buildRouterEncodedData(callHookData); // register token to gateway + ERC20PresetMinterPauser(address(nativeToken)).mint(address(token), nativeTokenTotalFee); + vm.prank(address(token)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + vm.mockCall( address(token), abi.encodeWithSignature("isArbitrumEnabled()"), @@ -244,6 +276,10 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { vm.prank(user); token.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); @@ -292,10 +328,18 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { assertEq(seqNum1, abi.encode(1), "Invalid seqNum1"); } - function test_outboundTransferCustomRefund_revert_InsufficientAllowance() public virtual override { + function test_outboundTransferCustomRefund_revert_InsufficientAllowance() + public + virtual + override + { uint256 tooManyTokens = 500 ether; // register token to gateway + ERC20PresetMinterPauser(address(nativeToken)).mint(address(token), nativeTokenTotalFee); + vm.prank(address(token)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + vm.mockCall( address(token), abi.encodeWithSignature("isArbitrumEnabled()"), @@ -313,7 +357,7 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { vm.prank(router); vm.expectRevert("ERC20: insufficient allowance"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + l1Gateway.outboundTransferCustomRefund( address(token), user, user, @@ -325,9 +369,18 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { } function test_registerTokenToL2(address l1Token, address l2Token) public override { - vm.assume(l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS); + vm.assume( + l1Token != FOUNDRY_CHEATCODE_ADDRESS && + l2Token != FOUNDRY_CHEATCODE_ADDRESS && + l1Token != address(0) + ); vm.deal(l1Token, 100 ether); + // approve fees + ERC20PresetMinterPauser(address(nativeToken)).mint(address(l1Token), nativeTokenTotalFee); + vm.prank(address(l1Token)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // event checkers vm.expectEmit(true, true, true, true); emit TokenSet(l1Token, l2Token); @@ -376,9 +429,18 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { } function test_registerTokenToL2_CustomRefund(address l1Token, address l2Token) public override { - vm.assume(l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS); + vm.assume( + l1Token != FOUNDRY_CHEATCODE_ADDRESS && + l2Token != FOUNDRY_CHEATCODE_ADDRESS && + l1Token != address(0) + ); vm.deal(l1Token, 100 ether); + // approve fees + ERC20PresetMinterPauser(address(nativeToken)).mint(address(l1Token), nativeTokenTotalFee); + vm.prank(address(l1Token)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // event checkers vm.expectEmit(true, true, true, true); emit TokenSet(l1Token, l2Token); @@ -448,6 +510,8 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { } function test_registerTokenToL2_revert_NoUpdateToDifferentAddress() public override { + ERC20PresetMinterPauser(address(nativeToken)).mint(address(token), nativeTokenTotalFee); + // register token to gateway vm.mockCall( address(token), @@ -457,7 +521,8 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { // set initial address address initialL2TokenAddress = makeAddr("initial"); - vm.prank(address(token)); + vm.startPrank(address(token)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( initialL2TokenAddress, maxGas, @@ -465,6 +530,7 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { maxSubmissionCost, nativeTokenTotalFee ); + vm.stopPrank(); assertEq( L1OrbitCustomGateway(address(l1Gateway)).l1ToL2Token(address(token)), initialL2TokenAddress @@ -472,7 +538,9 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { // try to set different one address differentL2TokenAddress = makeAddr("different"); - vm.prank(address(token)); + vm.startPrank(address(token)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + vm.expectRevert("NO_UPDATE_TO_DIFFERENT_ADDR"); L1OrbitCustomGateway(address(l1Gateway)).registerTokenToL2( differentL2TokenAddress, diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index bfc2557c9f..b2a85662a3 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -4,15 +4,20 @@ pragma solidity ^0.8.0; import { L1ERC20GatewayTest } from "./L1ERC20Gateway.t.sol"; import "contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol"; - +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20PresetMinterPauser } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { + ERC20 public nativeToken; uint256 public nativeTokenTotalFee; function setUp() public override { inbox = address(new ERC20InboxMock()); + nativeToken = ERC20(address(new ERC20PresetMinterPauser("X", "Y"))); + ERC20PresetMinterPauser(address(nativeToken)).mint(user, 1_000_000 ether); + ERC20InboxMock(inbox).setMockNativeToken(address(nativeToken)); l1Gateway = new L1OrbitERC20Gateway(); L1OrbitERC20Gateway(address(l1Gateway)).initialize( @@ -59,6 +64,10 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { vm.prank(user); token.approve(address(l1Gateway), depositAmount); + // approve fees + vm.prank(user); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // expect events vm.expectEmit(true, true, true, true); emit TicketData(maxSubmissionCost); @@ -104,12 +113,10 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { } function test_outboundTransfer_revert_NotAllowedToBridgeFeeToken() public { - address nativeFeeToken = address(50000); - // trigger deposit vm.prank(router); vm.expectRevert("NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); - l1Gateway.outboundTransfer(nativeFeeToken, user, 100, maxGas, gasPriceBid, ""); + l1Gateway.outboundTransfer(address(nativeToken), user, 100, maxGas, gasPriceBid, ""); } function test_outboundTransferCustomRefund() public override { @@ -122,6 +129,10 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { bytes memory callHookData = ""; bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + // approve fees + vm.prank(user); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // approve token vm.prank(user); token.approve(address(l1Gateway), depositAmount); @@ -172,13 +183,11 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { } function test_outboundTransferCustomRefund_revert_NotAllowedToBridgeFeeToken() public { - address nativeFeeToken = address(50000); - // trigger deposit vm.prank(router); vm.expectRevert("NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); l1Gateway.outboundTransferCustomRefund( - nativeFeeToken, + address(nativeToken), creditBackAddress, user, 100, diff --git a/test-foundry/L1OrbitGatewayRouter.t.sol b/test-foundry/L1OrbitGatewayRouter.t.sol index 599502f3a7..a263ebb543 100644 --- a/test-foundry/L1OrbitGatewayRouter.t.sol +++ b/test-foundry/L1OrbitGatewayRouter.t.sol @@ -12,12 +12,19 @@ import { L1OrbitCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1O import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { ERC20PresetMinterPauser } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; +import "forge-std/console.sol"; + contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { L1OrbitGatewayRouter public l1OrbitRouter; + ERC20 public nativeToken; uint256 public nativeTokenTotalFee; function setUp() public override { inbox = address(new ERC20InboxMock()); + 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)); defaultGateway = address(new L1OrbitERC20Gateway()); @@ -42,7 +49,8 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { address[] memory gateways = new address[](1); gateways[0] = address(new L1OrbitERC20Gateway()); - vm.prank(owner); + vm.startPrank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); l1OrbitRouter.setGateways( tokens, gateways, @@ -64,7 +72,8 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { address[] memory gateways = new address[](1); gateways[0] = address(1); - vm.prank(owner); + vm.startPrank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); l1OrbitRouter.setGateways( tokens, gateways, @@ -89,7 +98,8 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); // set default gateway - vm.prank(owner); + vm.startPrank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); l1OrbitRouter.setDefaultGateway( address(defaultGateway), maxGas, @@ -97,22 +107,30 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { maxSubmissionCost, nativeTokenTotalFee ); + vm.stopPrank(); // create token ERC20PresetMinterPauser token = new ERC20PresetMinterPauser("X", "Y"); token.mint(user, 10000); - vm.prank(user); - token.approve(defaultGateway, 103); // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); uint256 l1GatewayBalanceBefore = token.balanceOf(address(defaultGateway)); + uint256 userNativeTokenBalanceBefore = nativeToken.balanceOf(user); /// deposit data - address to = address(401); uint256 amount = 103; + address to = address(401); bytes memory userEncodedData = abi.encode(maxSubmissionCost, "", nativeTokenTotalFee); + /// approve tokens + vm.prank(user); + token.approve(address(defaultGateway), amount); + + // approve fees + vm.prank(user); + nativeToken.approve(address(defaultGateway), nativeTokenTotalFee); + // expect event vm.expectEmit(true, true, true, true); emit TransferRouted(address(token), user, to, address(defaultGateway)); @@ -131,11 +149,16 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { amount, "Wrong defaultGateway balance" ); + + uint256 userNativeTokenBalanceAfter = nativeToken.balanceOf(user); + assertEq( + userNativeTokenBalanceBefore - userNativeTokenBalanceAfter, + nativeTokenTotalFee, + "Wrong user native token balance" + ); } function test_outboundTransfer_revert_NotAllowedToBridgeFeeToken() public { - address nativeFeeToken = address(50000); - // init default gateway L1OrbitERC20Gateway(defaultGateway).initialize( makeAddr("defaultGatewayCounterpart"), @@ -146,7 +169,8 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); // set default gateway - vm.prank(owner); + vm.startPrank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); l1OrbitRouter.setDefaultGateway( address(defaultGateway), maxGas, @@ -154,11 +178,12 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { maxSubmissionCost, nativeTokenTotalFee ); + vm.stopPrank(); /// deposit it vm.prank(user); vm.expectRevert("NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); - l1Router.outboundTransfer(nativeFeeToken, user, 100, maxGas, gasPriceBid, ""); + l1Router.outboundTransfer(address(nativeToken), user, 100, maxGas, gasPriceBid, ""); } function test_outboundTransferCustomRefund() public override { @@ -172,7 +197,8 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); // set default gateway - vm.prank(owner); + vm.startPrank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); l1OrbitRouter.setDefaultGateway( address(defaultGateway), maxGas, @@ -180,16 +206,16 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { maxSubmissionCost, nativeTokenTotalFee ); + vm.stopPrank(); // create token ERC20PresetMinterPauser token = new ERC20PresetMinterPauser("X", "Y"); token.mint(user, 10000); - vm.prank(user); - token.approve(defaultGateway, 103); // snapshot state before uint256 userBalanceBefore = token.balanceOf(user); uint256 l1GatewayBalanceBefore = token.balanceOf(address(defaultGateway)); + uint256 userNativeTokenBalanceBefore = nativeToken.balanceOf(user); /// deposit data address refundTo = address(400); @@ -197,6 +223,14 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { uint256 amount = 103; bytes memory userEncodedData = abi.encode(maxSubmissionCost, "", nativeTokenTotalFee); + // approve fees + vm.prank(user); + nativeToken.approve(defaultGateway, nativeTokenTotalFee); + + // approve tokens + vm.prank(user); + token.approve(defaultGateway, amount); + // expect event vm.expectEmit(true, true, true, true); emit TransferRouted(address(token), user, to, address(defaultGateway)); @@ -223,11 +257,16 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { amount, "Wrong defaultGateway balance" ); + + uint256 userNativeTokenBalanceAfter = nativeToken.balanceOf(user); + assertEq( + userNativeTokenBalanceBefore - userNativeTokenBalanceAfter, + nativeTokenTotalFee, + "Wrong user native token balance" + ); } function test_outboundTransferCustomRefund_revert_NotAllowedToBridgeFeeToken() public { - address nativeFeeToken = address(50000); - // init default gateway L1OrbitERC20Gateway(defaultGateway).initialize( makeAddr("defaultGatewayCounterpart"), @@ -238,7 +277,8 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); // set default gateway - vm.prank(owner); + vm.startPrank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); l1OrbitRouter.setDefaultGateway( address(defaultGateway), maxGas, @@ -246,12 +286,13 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { maxSubmissionCost, nativeTokenTotalFee ); + vm.stopPrank(); /// deposit it vm.prank(user); vm.expectRevert("NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); l1Router.outboundTransferCustomRefund( - nativeFeeToken, + address(nativeToken), user, user, 100, @@ -272,6 +313,10 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { makeAddr("l2BeaconProxyFactory") ); + // approve fees + vm.prank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); + // event checkers vm.expectEmit(true, true, true, true); emit DefaultGatewayUpdated(address(newL1DefaultGateway)); @@ -319,6 +364,10 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { function test_setDefaultGateway_AddressZero() public override { address newL1DefaultGateway = address(0); + // approve fees + vm.prank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); + // event checkers vm.expectEmit(true, true, true, true); emit DefaultGatewayUpdated(address(newL1DefaultGateway)); @@ -381,6 +430,14 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ERC20 customToken = new ERC20("X", "Y"); vm.deal(address(customToken), 100 ether); + // approve fees + ERC20PresetMinterPauser(address(nativeToken)).mint( + address(customToken), + nativeTokenTotalFee + ); + vm.prank(address(customToken)); + nativeToken.approve(address(customGateway), nativeTokenTotalFee); + // register token to gateway vm.mockCall( address(customToken), @@ -397,6 +454,18 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { nativeTokenTotalFee ); + ERC20PresetMinterPauser(address(nativeToken)).mint( + address(customToken), + nativeTokenTotalFee + ); + + // snapshot state before + uint256 senderNativeTokenBalanceBefore = nativeToken.balanceOf(address(customToken)); + + // approve fees + vm.prank(address(customToken)); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); + // expect events vm.expectEmit(true, true, true, true); emit GatewaySet(address(customToken), address(customGateway)); @@ -440,6 +509,13 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { "Gateway not set" ); + uint256 senderNativeTokenBalanceAfter = nativeToken.balanceOf(address(customToken)); + assertEq( + senderNativeTokenBalanceBefore - senderNativeTokenBalanceAfter, + nativeTokenTotalFee, + "Wrong sender native token balance" + ); + assertEq(seqNum, 1, "Invalid seqNum"); } @@ -454,6 +530,13 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { vm.deal(address(customToken), 100 ether); // register token to gateway + ERC20PresetMinterPauser(address(nativeToken)).mint( + address(customToken), + nativeTokenTotalFee + ); + vm.prank(address(customToken)); + nativeToken.approve(address(customGateway), nativeTokenTotalFee); + vm.mockCall( address(customToken), abi.encodeWithSignature("isArbitrumEnabled()"), @@ -469,6 +552,14 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { nativeTokenTotalFee ); + // approve fees + ERC20PresetMinterPauser(address(nativeToken)).mint( + address(customToken), + nativeTokenTotalFee + ); + vm.prank(address(customToken)); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); + // expect events vm.expectEmit(true, true, true, true); emit GatewaySet(address(customToken), address(customGateway)); @@ -532,6 +623,10 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { vm.deal(address(token), 100 ether); // register token to gateway + ERC20PresetMinterPauser(address(nativeToken)).mint(address(token), nativeTokenTotalFee); + vm.prank(token); + nativeToken.approve(address(initialGateway), nativeTokenTotalFee); + vm.mockCall( address(token), abi.encodeWithSignature("isArbitrumEnabled()"), @@ -548,6 +643,10 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); // initially set gateway for token + ERC20PresetMinterPauser(address(nativeToken)).mint(address(token), nativeTokenTotalFee); + vm.prank(address(token)); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); + vm.prank(address(token)); l1OrbitRouter.setGateway( initialGateway, @@ -678,6 +777,10 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); // register tokens to gateways + ERC20PresetMinterPauser(address(nativeToken)).mint(tokens[i], nativeTokenTotalFee); + vm.prank(tokens[i]); + nativeToken.approve(address(gateways[i]), nativeTokenTotalFee); + vm.deal(tokens[i], 100 ether); vm.prank(tokens[i]); L1OrbitCustomGateway(gateways[i]).registerTokenToL2( @@ -690,6 +793,10 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); } + // approve fees + vm.prank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); + // expect events vm.expectEmit(true, true, true, true); emit GatewaySet(tokens[0], gateways[0]); @@ -750,6 +857,10 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { vm.deal(address(token), 100 ether); // register token to gateway + ERC20PresetMinterPauser(address(nativeToken)).mint(address(token), nativeTokenTotalFee); + vm.prank(address(token)); + nativeToken.approve(initialGateway, nativeTokenTotalFee); + vm.mockCall( address(token), abi.encodeWithSignature("isArbitrumEnabled()"), @@ -766,6 +877,10 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { ); // initially set gateway for token + ERC20PresetMinterPauser(address(nativeToken)).mint(address(token), nativeTokenTotalFee); + vm.prank(address(token)); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); + vm.prank(address(token)); l1OrbitRouter.setGateway( initialGateway, @@ -780,6 +895,10 @@ contract L1OrbitGatewayRouterTest is L1GatewayRouterTest { //// now set to zero addr address newGateway = address(0); + // approve fees + vm.prank(owner); + nativeToken.approve(address(l1OrbitRouter), nativeTokenTotalFee); + // expect events vm.expectEmit(true, true, true, true); emit GatewaySet(token, newGateway); diff --git a/test-foundry/L1OrbitReverseCustomGateway.t.sol b/test-foundry/L1OrbitReverseCustomGateway.t.sol index d8976b6441..2300b1fb0d 100644 --- a/test-foundry/L1OrbitReverseCustomGateway.t.sol +++ b/test-foundry/L1OrbitReverseCustomGateway.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; -import { L1OrbitCustomGatewayTest, ERC20InboxMock, TestERC20, IERC20 } from "./L1OrbitCustomGateway.t.sol"; +import { L1OrbitCustomGatewayTest, ERC20InboxMock, TestERC20, IERC20, ERC20, ERC20PresetMinterPauser } from "./L1OrbitCustomGateway.t.sol"; import { L1OrbitReverseCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol"; import { MintableTestCustomTokenL1, ReverseTestCustomTokenL1 } from "contracts/tokenbridge/test/TestCustomTokenL1.sol"; import { IInbox } from "contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol"; @@ -10,6 +10,10 @@ import { IInbox } from "contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol"; contract L1OrbitReverseCustomGatewayTest is L1OrbitCustomGatewayTest { function setUp() public override { inbox = address(new ERC20InboxMock()); + 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)); l1Gateway = new L1OrbitReverseCustomGateway(); L1OrbitReverseCustomGateway(address(l1Gateway)).initialize(l2Gateway, router, inbox, owner); @@ -80,6 +84,14 @@ contract L1OrbitReverseCustomGatewayTest is L1OrbitCustomGatewayTest { bytes memory callHookData = ""; bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + // approve fees + ERC20PresetMinterPauser(address(nativeToken)).mint( + address(bridgedToken), + nativeTokenTotalFee + ); + vm.prank(address(bridgedToken)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // register token to gateway vm.mockCall( address(bridgedToken), @@ -101,6 +113,10 @@ contract L1OrbitReverseCustomGatewayTest is L1OrbitCustomGatewayTest { vm.prank(user); bridgedToken.approve(address(l1Gateway), amount); + // approve fees + vm.prank(user); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // event checkers vm.expectEmit(true, true, true, true); emit TicketData(maxSubmissionCost); @@ -157,6 +173,14 @@ contract L1OrbitReverseCustomGatewayTest is L1OrbitCustomGatewayTest { bytes memory callHookData = ""; bytes memory routerEncodedData = buildRouterEncodedData(callHookData); + // approve fees + ERC20PresetMinterPauser(address(nativeToken)).mint( + address(bridgedToken), + nativeTokenTotalFee + ); + vm.prank(address(bridgedToken)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // register token to gateway vm.mockCall( address(bridgedToken), @@ -178,6 +202,10 @@ contract L1OrbitReverseCustomGatewayTest is L1OrbitCustomGatewayTest { vm.prank(user); bridgedToken.approve(address(l1Gateway), amount); + // approve fees + vm.prank(user); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // event checkers vm.expectEmit(true, true, true, true); emit TicketData(maxSubmissionCost); @@ -231,6 +259,14 @@ contract L1OrbitReverseCustomGatewayTest is L1OrbitCustomGatewayTest { uint256 tooManyTokens = 500 ether; + // approve fees + ERC20PresetMinterPauser(address(nativeToken)).mint( + address(bridgedToken), + nativeTokenTotalFee + ); + vm.prank(address(bridgedToken)); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + // register token to gateway vm.mockCall( address(bridgedToken), @@ -244,10 +280,13 @@ contract L1OrbitReverseCustomGatewayTest is L1OrbitCustomGatewayTest { maxGas, gasPriceBid, maxSubmissionCost, - makeAddr("creditBackAddress"), + creditBackAddress, nativeTokenTotalFee ); + vm.prank(user); + nativeToken.approve(address(l1Gateway), nativeTokenTotalFee); + vm.prank(router); vm.expectRevert("ERC20: burn amount exceeds balance"); l1Gateway.outboundTransferCustomRefund( From bdb6d594468586d06008740ca7ca8e693e24db13 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 19 May 2023 15:53:12 +0200 Subject: [PATCH 064/163] Use isRouter() --- contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol | 2 +- contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol index 9bd4623e84..fd6c891afe 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol @@ -199,7 +199,7 @@ contract L1OrbitCustomGateway is L1CustomGateway { address nativeFeeToken = IERC20Bridge(address(getBridge(_inbox))).nativeToken(); uint256 inboxNativeTokenBalance = IERC20(nativeFeeToken).balanceOf(_inbox); if (inboxNativeTokenBalance < _totalFeeAmount) { - address transferFrom = msg.sender == router ? _user : msg.sender; + address transferFrom = isRouter(msg.sender) ? _user : msg.sender; IERC20(nativeFeeToken).safeTransferFrom( transferFrom, _inbox, diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index 5724dba3a7..5642ffad73 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -99,7 +99,7 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { address nativeFeeToken = _getNativeFeeToken(); uint256 inboxNativeTokenBalance = IERC20(nativeFeeToken).balanceOf(_inbox); if (inboxNativeTokenBalance < _totalFeeAmount) { - address transferFrom = msg.sender == router ? _user : msg.sender; + address transferFrom = isRouter(msg.sender) ? _user : msg.sender; IERC20(nativeFeeToken).safeTransferFrom( transferFrom, _inbox, From 981bd973bcf0b6c4919b1147e87297801d5be3ad Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 19 May 2023 16:17:13 +0200 Subject: [PATCH 065/163] Fuzz constraints --- test-foundry/L1OrbitCustomGateway.t.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test-foundry/L1OrbitCustomGateway.t.sol b/test-foundry/L1OrbitCustomGateway.t.sol index 65e09c298d..45a4180f7d 100644 --- a/test-foundry/L1OrbitCustomGateway.t.sol +++ b/test-foundry/L1OrbitCustomGateway.t.sol @@ -432,7 +432,9 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { vm.assume( l1Token != FOUNDRY_CHEATCODE_ADDRESS && l2Token != FOUNDRY_CHEATCODE_ADDRESS && - l1Token != address(0) + l1Token != address(0) && + l1Token != router && + l1Token != creditBackAddress ); vm.deal(l1Token, 100 ether); From 12642537e03b6aef2b109038d20723b5c25a4617 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 16 May 2023 09:51:54 +0200 Subject: [PATCH 066/163] Add setup for integration tests --- .gitmodules | 6 +- files/local/network.json | 50 ++++++ lib/nitro-contracts | 1 + package.json | 2 +- scripts/genTokenBridge.ts | 17 -- scripts/local-deployment/deployBridge.ts | 178 ++++++++++++++++++++ scripts/local-deployment/genTokenBridge.ts | 25 +++ scripts/{ => local-deployment}/testSetup.ts | 46 +++-- test-foundry/IOwnable.sol | 10 ++ test-foundry/Integration.t.sol | 176 +++++++++++++++++++ test-foundry/util/TestUtil.sol | 12 ++ 11 files changed, 493 insertions(+), 30 deletions(-) create mode 100644 files/local/network.json create mode 160000 lib/nitro-contracts delete mode 100644 scripts/genTokenBridge.ts create mode 100644 scripts/local-deployment/deployBridge.ts create mode 100644 scripts/local-deployment/genTokenBridge.ts rename scripts/{ => local-deployment}/testSetup.ts (71%) create mode 100644 test-foundry/IOwnable.sol create mode 100644 test-foundry/Integration.t.sol create mode 100644 test-foundry/util/TestUtil.sol diff --git a/.gitmodules b/.gitmodules index 4c1b977a36..3877275564 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "lib/forge-std"] path = lib/forge-std - url = https://github.com/foundry-rs/forge-std \ No newline at end of file + url = https://github.com/foundry-rs/forge-std +[submodule "lib/nitro-contracts"] + path = lib/nitro-contracts + url = git@github.com:OffchainLabs/nitro-private.git + branch = develop diff --git a/files/local/network.json b/files/local/network.json new file mode 100644 index 0000000000..a12303a51f --- /dev/null +++ b/files/local/network.json @@ -0,0 +1,50 @@ +{ + "l1Network": { + "blockTime": 10, + "chainID": 1337, + "explorerUrl": "", + "isCustom": true, + "name": "EthLocal", + "partnerChainIDs": [ + 1337 + ], + "isArbitrum": false + }, + "l2Network": { + "chainID": 1337, + "confirmPeriodBlocks": 20, + "ethBridge": { + "bridge": "0xce08c107a607e6ddf58da38dc1efbf9228abe2c4", + "inbox": "0x780eb6fbe92db687ce5e644c66d10d66441c86d2", + "outbox": "0x6E45Bd4B4Cd028521BDDFa11476735341DfD8F33", + "rollup": "0x0bb03f5c44ce2b206364f794bb861f5e28aface3", + "sequencerInbox": "0x164f0489124f125e7b750f276ea83e9961a6d333" + }, + "nativeToken": "0xa6e41ffd769491a42a6e5ce453259b93983a22ef", + "explorerUrl": "", + "isArbitrum": true, + "isCustom": true, + "name": "ArbLocal", + "partnerChainID": 1337, + "retryableLifetimeSeconds": 604800, + "nitroGenesisBlock": 0, + "nitroGenesisL1Block": 0, + "depositTimeout": 900000, + "tokenBridge": { + "l1CustomGateway": "0x1A3Ef0413FdE0bf110A363f25c3fE6b527f3A8d4", + "l1ERC20Gateway": "0x7696e37e86B993aC1CE27feed48Fa154cB8B2EDa", + "l1GatewayRouter": "0xE85035F1145aC49333d105632a0d254E479a75bE", + "l1MultiCall": "", + "l1ProxyAdmin": "0xe7e96cEF8812D2d24ADD2de592b5C786f915f64b", + "l1Weth": "", + "l1WethGateway": "", + "l2CustomGateway": "0xeB0283a324B1E5A22fe6d3295E7c54169c2F95CA", + "l2ERC20Gateway": "0x2cc42F00be0fE77FF5Ba18e6e039f373e62c13F2", + "l2GatewayRouter": "0xe7e8B4930802Ce5909cB2A2b8d2e447837158660", + "l2Multicall": "", + "l2ProxyAdmin": "0xEc6c3dF641BDe740992898f25A780aab35d0062f", + "l2Weth": "", + "l2WethGateway": "" + } + } +} \ No newline at end of file diff --git a/lib/nitro-contracts b/lib/nitro-contracts new file mode 160000 index 0000000000..2497d70a32 --- /dev/null +++ b/lib/nitro-contracts @@ -0,0 +1 @@ +Subproject commit 2497d70a322c05309f11267fd7913e596ac12ce9 diff --git a/package.json b/package.json index 20165710ef..a64ae9fba7 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "test:l2": "hardhat test test/*.l2.ts", "test:unit": "forge test", "test:storage": "./scripts/storage_layout_test.bash", - "test:deploy:tokenbridge": "ts-node ./scripts/genTokenBridge.ts", + "test:deploy:tokenbridge": "ts-node ./scripts/local-deployment/genTokenBridge.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", diff --git a/scripts/genTokenBridge.ts b/scripts/genTokenBridge.ts deleted file mode 100644 index 992e45971a..0000000000 --- a/scripts/genTokenBridge.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { setupNetworks, config } from './testSetup' -import * as fs from 'fs' - -async function main() { - const { l1Network, l2Network } = await setupNetworks( - config.ethUrl, - config.arbUrl - ) - - fs.writeFileSync( - './files/local/network.json', - JSON.stringify({ l1Network, l2Network }, null, 2) - ) - console.log('network.json updated') -} - -main().then(() => console.log('Done.')) diff --git a/scripts/local-deployment/deployBridge.ts b/scripts/local-deployment/deployBridge.ts new file mode 100644 index 0000000000..1de929a3c5 --- /dev/null +++ b/scripts/local-deployment/deployBridge.ts @@ -0,0 +1,178 @@ +import { Contract, ContractFactory, Signer, constants } from 'ethers' +import { + BeaconProxyFactory__factory, + L1OrbitCustomGateway__factory, + L1OrbitERC20Gateway__factory, + L1OrbitGatewayRouter__factory, + L2CustomGateway__factory, + L2ERC20Gateway__factory, + L2GatewayRouter__factory, + ProxyAdmin__factory, + StandardArbERC20__factory, + TransparentUpgradeableProxy__factory, + UpgradeableBeacon__factory, +} from '../../build/types' + +async function deployContractBehindProxy< + T extends ContractFactory, + U extends Contract +>( + deployer: Signer, + logicFactory: new (deployer: Signer) => T, + proxyAdmin: string, + contractFactory: (address: string, signer: Signer) => U +): Promise { + const logicContract = await new logicFactory(deployer).deploy() + await logicContract.deployed() + + const proxyContract = await new TransparentUpgradeableProxy__factory( + deployer + ).deploy(logicContract.address, proxyAdmin, '0x') + await proxyContract.deployed() + + return contractFactory(proxyContract.address, deployer) +} + +export const deployErc20L1 = async (deployer: Signer) => { + const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() + await proxyAdmin.deployed() + console.log('proxyAdmin', proxyAdmin.address) + + const router = await deployContractBehindProxy( + deployer, + L1OrbitGatewayRouter__factory, + proxyAdmin.address, + L1OrbitGatewayRouter__factory.connect + ) + + const standardGateway = await deployContractBehindProxy( + deployer, + L1OrbitERC20Gateway__factory, + proxyAdmin.address, + L1OrbitERC20Gateway__factory.connect + ) + + const customGateway = await deployContractBehindProxy( + deployer, + L1OrbitCustomGateway__factory, + proxyAdmin.address, + L1OrbitCustomGateway__factory.connect + ) + + return { + proxyAdmin, + router, + standardGateway, + customGateway, + } +} + +export const deployErc20L2 = async (deployer: Signer) => { + const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() + await proxyAdmin.deployed() + + const router = await deployContractBehindProxy( + deployer, + L2GatewayRouter__factory, + proxyAdmin.address, + L2GatewayRouter__factory.connect + ) + + const standardGateway = await deployContractBehindProxy( + deployer, + L2ERC20Gateway__factory, + proxyAdmin.address, + L2ERC20Gateway__factory.connect + ) + + const customGateway = await deployContractBehindProxy( + deployer, + L2CustomGateway__factory, + proxyAdmin.address, + L2CustomGateway__factory.connect + ) + + const standardArbERC20 = await new StandardArbERC20__factory( + deployer + ).deploy() + await standardArbERC20.deployed() + + const beacon = await new UpgradeableBeacon__factory(deployer).deploy( + standardArbERC20.address + ) + await beacon.deployed() + + const beaconProxyFactory = await new BeaconProxyFactory__factory( + deployer + ).deploy() + await beaconProxyFactory.deployed() + + return { + proxyAdmin, + router, + standardGateway, + customGateway, + standardArbERC20, + beacon, + beaconProxyFactory, + } +} + +export const deployErc20AndInit = async ( + l1Signer: Signer, + l2Signer: Signer, + inboxAddress: string +) => { + console.log('deploying l1') + const l1 = await deployErc20L1(l1Signer) + + console.log('deploying l2') + const l2 = await deployErc20L2(l2Signer) + + console.log('initialising L2') + await l2.router.initialize(l1.router.address, l2.standardGateway.address) + await ( + await l2.standardGateway.initialize( + l1.standardGateway.address, + l2.router.address, + l2.beaconProxyFactory.address + ) + ).wait() + await ( + await l2.customGateway.initialize( + l1.customGateway.address, + l2.router.address + ) + ).wait() + + console.log('initialising L1') + await ( + await l1.router.initialize( + await l1Signer.getAddress(), + l1.standardGateway.address, + constants.AddressZero, + l2.router.address, + inboxAddress + ) + ).wait() + + await ( + await l1.standardGateway.initialize( + l2.standardGateway.address, + l1.router.address, + inboxAddress, + await l2.beaconProxyFactory.cloneableProxyHash(), + l2.beaconProxyFactory.address + ) + ).wait() + await ( + await l1.customGateway.initialize( + l2.customGateway.address, + l1.router.address, + inboxAddress, + await l1Signer.getAddress() + ) + ).wait() + + return { l1, l2 } +} diff --git a/scripts/local-deployment/genTokenBridge.ts b/scripts/local-deployment/genTokenBridge.ts new file mode 100644 index 0000000000..eafcac64bb --- /dev/null +++ b/scripts/local-deployment/genTokenBridge.ts @@ -0,0 +1,25 @@ +import { ethers } from 'ethers' +import { setupNetworks, config, getSigner } from './testSetup' +import * as fs from 'fs' + +async function main() { + const ethProvider = new ethers.providers.JsonRpcProvider(config.ethUrl) + const arbProvider = new ethers.providers.JsonRpcProvider(config.arbUrl) + + const ethDeployer = getSigner(ethProvider, config.ethKey) + const arbDeployer = getSigner(arbProvider, config.arbKey) + const { l1Network, l2Network } = await setupNetworks( + ethDeployer, + arbDeployer, + config.ethUrl, + config.arbUrl + ) + + fs.writeFileSync( + './files/local/network.json', + JSON.stringify({ l1Network, l2Network }, null, 2) + ) + console.log('network.json updated') +} + +main().then(() => console.log('Done.')) diff --git a/scripts/testSetup.ts b/scripts/local-deployment/testSetup.ts similarity index 71% rename from scripts/testSetup.ts rename to scripts/local-deployment/testSetup.ts index 88f193dd8e..f9ae0967cc 100644 --- a/scripts/testSetup.ts +++ b/scripts/local-deployment/testSetup.ts @@ -4,13 +4,17 @@ import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' import { execSync } from 'child_process' import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' -import { Signer } from 'ethers' +import { Signer, Wallet } from 'ethers' +import { L2GatewayRouter__factory } from '../../build/types' +import { deployErc20AndInit } from './deployBridge' dotenv.config() export const config = { arbUrl: process.env['ARB_URL'] as string, ethUrl: process.env['ETH_URL'] as string, + arbKey: process.env['ARB_KEY'] as string, + ethKey: process.env['ETH_KEY'] as string, } export const getCustomNetworks = async ( @@ -92,27 +96,40 @@ export const getCustomNetworks = async ( } } -export const setupNetworks = async (l1Url: string, l2Url: string) => { +export const setupNetworks = async ( + l1Deployer: Signer, + l2Deployer: Signer, + l1Url: string, + l2Url: string +) => { const { l1Network, l2Network: coreL2Network } = await getCustomNetworks( l1Url, l2Url ) - const l2Network: L2Network & { nativeToken: string } = { + + new L2GatewayRouter__factory(l1Deployer).deploy() + + const { l1: l1Contracts, l2: l2Contracts } = await deployErc20AndInit( + l1Deployer, + l2Deployer, + coreL2Network.ethBridge.inbox + ) + const l2Network: L2Network = { ...coreL2Network, tokenBridge: { - l1CustomGateway: '', - l1ERC20Gateway: '', - l1GatewayRouter: '', + l1CustomGateway: l1Contracts.customGateway.address, + l1ERC20Gateway: l1Contracts.standardGateway.address, + l1GatewayRouter: l1Contracts.router.address, l1MultiCall: '', - l1ProxyAdmin: '', + l1ProxyAdmin: l1Contracts.proxyAdmin.address, l1Weth: '', l1WethGateway: '', - l2CustomGateway: '', - l2ERC20Gateway: '', - l2GatewayRouter: '', + l2CustomGateway: l2Contracts.customGateway.address, + l2ERC20Gateway: l2Contracts.standardGateway.address, + l2GatewayRouter: l2Contracts.router.address, l2Multicall: '', - l2ProxyAdmin: '', + l2ProxyAdmin: l2Contracts.proxyAdmin.address, l2Weth: '', l2WethGateway: '', }, @@ -129,6 +146,13 @@ export const setupNetworks = async (l1Url: string, l2Url: string) => { } } +export const getSigner = (provider: JsonRpcProvider, key?: string) => { + if (!key && !provider) + throw new Error('Provide at least one of key or provider.') + if (key) return new Wallet(key).connect(provider) + else return provider.getSigner(0) +} + export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)) } diff --git a/test-foundry/IOwnable.sol b/test-foundry/IOwnable.sol new file mode 100644 index 0000000000..20735f0dd2 --- /dev/null +++ b/test-foundry/IOwnable.sol @@ -0,0 +1,10 @@ +// Copyright 2021-2022, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE +// SPDX-License-Identifier: BUSL-1.1 + +// solhint-disable-next-line compiler-version +pragma solidity >=0.4.21 <0.9.0; + +interface IOwnable { + function owner() external view returns (address); +} diff --git a/test-foundry/Integration.t.sol b/test-foundry/Integration.t.sol new file mode 100644 index 0000000000..4d9adaa195 --- /dev/null +++ b/test-foundry/Integration.t.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.0; + +import "forge-std/Test.sol"; +import { L1GatewayRouterTest } from "./L1GatewayRouter.t.sol"; +import { ERC20InboxMock } from "contracts/tokenbridge/test/InboxMock.sol"; +import { L1OrbitERC20Gateway } from "contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol"; +import { L1OrbitGatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol"; +import { L2GatewayRouter } from "contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol"; +import { L1GatewayRouter } from "contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol"; +import { L1OrbitCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol"; +import { ERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20PresetMinterPauser } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; +import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; + +import { ERC20Inbox } from "lib/nitro-contracts/contracts/src/bridge/ERC20Inbox.sol"; +import { ERC20Bridge } from "lib/nitro-contracts/contracts/src/bridge/ERC20Bridge.sol"; +import { ERC20PresetFixedSupply } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol"; +import { IOwnable } from "lib/nitro-contracts/contracts/src/bridge/IOwnable.sol"; +import { ISequencerInbox } from "lib/nitro-contracts/contracts/src/bridge/ISequencerInbox.sol"; +import "./util/TestUtil.sol"; + +contract IntegrationTest is Test { + address public owner = makeAddr("owner"); + address public user = makeAddr("user"); + address public counterpartGateway = makeAddr("counterpartGateway"); + address public rollup = makeAddr("rollup"); + address public seqInbox = makeAddr("seqInbox"); + address public l2Gateway = makeAddr("l2Gateway"); + bytes32 public cloneableProxyHash = bytes32("123"); + address public l2BeaconProxyFactory = makeAddr("l2BeaconProxyFactory"); + + ERC20PresetFixedSupply public nativeToken; + ERC20Inbox public inbox; + ERC20Bridge public bridge; + L1OrbitERC20Gateway public defaultGateway; + L1OrbitGatewayRouter public router; + IERC20 public token; + + function setUp() public { + // deploy token, bridge and inbox + nativeToken = new ERC20PresetFixedSupply("Appchain Token", "App", 100000000, address(this)); + inbox = ERC20Inbox(TestUtil.deployProxy(address(new ERC20Inbox()))); + bridge = ERC20Bridge(TestUtil.deployProxy(address(new ERC20Bridge()))); + + // init bridge and inbox + bridge.initialize(IOwnable(rollup), address(nativeToken)); + inbox.initialize(bridge, ISequencerInbox(seqInbox)); + vm.prank(rollup); + bridge.setDelayedInbox(address(inbox), true); + + // create default gateway and router + defaultGateway = L1OrbitERC20Gateway( + TestUtil.deployProxy(address(new L1OrbitERC20Gateway())) + ); + router = L1OrbitGatewayRouter(TestUtil.deployProxy(address(new L1OrbitGatewayRouter()))); + router.initialize( + owner, + address(defaultGateway), + address(0), + counterpartGateway, + address(inbox) + ); + defaultGateway.initialize( + l2Gateway, + address(router), + address(inbox), + cloneableProxyHash, + l2BeaconProxyFactory + ); + + // token to bridge + token = IERC20(address(new TestERC20())); + + // fund accounts + nativeToken.transfer(user, 1_000_000); + nativeToken.transfer(owner, 1_000_000); + vm.prank(user); + TestERC20(address(token)).mint(); + // vm.deal(owner, 100 ether); + // vm.deal(user, 100 ether); + } + + /* solhint-disable func-name-mixedcase */ + function test_depositNative() public { + uint256 depositAmount = 140; + vm.prank(user); + nativeToken.approve(address(bridge), 140); + + vm.prank(user); + inbox.depositERC20(depositAmount); + } + + function test_depositToken() public { + uint256 tokenDepositAmount = 250; + uint256 maxSubmissionCost = 0; + uint256 maxGas = 100000; + uint256 gasPriceBid = 3; + uint256 nativeTokenTotalFee = maxGas * gasPriceBid; + + /// set default gateway + vm.startPrank(owner); + nativeToken.approve(address(router), nativeTokenTotalFee); + router.setDefaultGateway( + address(defaultGateway), + maxGas, + gasPriceBid, + maxSubmissionCost, + nativeTokenTotalFee + ); + assertEq(router.defaultGateway(), address(defaultGateway), "Invalid defaultGateway"); + vm.stopPrank(); + + // snapshot state before + uint256 userTokenBalanceBefore = token.balanceOf(user); + uint256 l1GatewayBalanceBefore = token.balanceOf(address(defaultGateway)); + uint256 userNativeTokenBalanceBefore = nativeToken.balanceOf(user); + uint256 bridgeNativeTokenBalanceBefore = nativeToken.balanceOf(address(bridge)); + + { + /// do token deposit + vm.startPrank(user); + + token.approve(address(defaultGateway), tokenDepositAmount); + + nativeToken.approve(address(defaultGateway), nativeTokenTotalFee); + + address refundTo = user; + bytes memory userEncodedData = abi.encode(maxSubmissionCost, "", nativeTokenTotalFee); + router.outboundTransferCustomRefund( + address(token), + refundTo, + user, + tokenDepositAmount, + maxGas, + gasPriceBid, + userEncodedData + ); + + vm.stopPrank(); + } + + /// checks + { + uint256 userTokenBalanceAfter = token.balanceOf(user); + uint256 l1GatewayBalanceAfter = token.balanceOf(address(defaultGateway)); + uint256 userNativeTokenBalanceAfter = nativeToken.balanceOf(user); + uint256 bridgeNativeTokenBalanceAfter = nativeToken.balanceOf(address(bridge)); + + assertEq( + userTokenBalanceBefore - userTokenBalanceAfter, + tokenDepositAmount, + "Invalid user token balance" + ); + + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + tokenDepositAmount, + "Invalid default gateway token balance" + ); + + assertEq( + userNativeTokenBalanceBefore - userNativeTokenBalanceAfter, + nativeTokenTotalFee, + "Invalid user native token balance" + ); + + assertEq( + bridgeNativeTokenBalanceAfter - bridgeNativeTokenBalanceBefore, + nativeTokenTotalFee, + "Invalid user native token balance" + ); + } + } +} diff --git a/test-foundry/util/TestUtil.sol b/test-foundry/util/TestUtil.sol new file mode 100644 index 0000000000..2238b8cb42 --- /dev/null +++ b/test-foundry/util/TestUtil.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.17; + +import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; + +library TestUtil { + function deployProxy(address logic) public returns (address) { + ProxyAdmin pa = new ProxyAdmin(); + return address(new TransparentUpgradeableProxy(address(logic), address(pa), "")); + } +} From decaefa8f09183e7d5563e1c3493ec53f45be8ab Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 23 May 2023 14:34:00 +0200 Subject: [PATCH 067/163] Add integration tests for L1 Orbit --- .../tokenbridge/test/TestCustomTokenL1.sol | 128 +++++++++--- ...gration.t.sol => L1OrbitIntegration.t.sol} | 195 ++++++++++++++---- 2 files changed, 261 insertions(+), 62 deletions(-) rename test-foundry/{Integration.t.sol => L1OrbitIntegration.t.sol} (51%) diff --git a/contracts/tokenbridge/test/TestCustomTokenL1.sol b/contracts/tokenbridge/test/TestCustomTokenL1.sol index 359eef1d7f..f33216b6c1 100644 --- a/contracts/tokenbridge/test/TestCustomTokenL1.sol +++ b/contracts/tokenbridge/test/TestCustomTokenL1.sol @@ -6,8 +6,10 @@ import "../libraries/aeERC20.sol"; import "../ethereum/ICustomToken.sol"; import "../ethereum/gateway/L1CustomGateway.sol"; import "../ethereum/gateway/L1GatewayRouter.sol"; +import { IERC20Bridge } from "../libraries/IERC20Bridge.sol"; import "@openzeppelin/contracts/utils/Context.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; interface IL1CustomGateway { function registerTokenToL2( @@ -19,6 +21,17 @@ interface IL1CustomGateway { ) external payable returns (uint256); } +interface IL1OrbitCustomGateway { + function registerTokenToL2( + address _l2Address, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + address _creditBackAddress, + uint256 _feeAmount + ) external returns (uint256); +} + interface IGatewayRouter2 { function setGateway( address _gateway, @@ -29,10 +42,23 @@ interface IGatewayRouter2 { ) external payable returns (uint256); } +interface IOrbitGatewayRouter { + function setGateway( + address _gateway, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost, + address _creditBackAddress, + uint256 _feeAmount + ) external returns (uint256); + + function inbox() external returns (address); +} + contract TestCustomTokenL1 is aeERC20, ICustomToken { address public gateway; address public router; - bool private shouldRegisterGateway; + bool internal shouldRegisterGateway; constructor(address _gateway, address _router) { gateway = _gateway; @@ -52,7 +78,9 @@ contract TestCustomTokenL1 is aeERC20, ICustomToken { return ERC20Upgradeable.transferFrom(sender, recipient, amount); } - function balanceOf(address account) + function balanceOf( + address account + ) public view virtual @@ -78,7 +106,7 @@ contract TestCustomTokenL1 is aeERC20, ICustomToken { uint256 valueForGateway, uint256 valueForRouter, address creditBackAddress - ) public payable override { + ) public payable virtual override { // we temporarily set `shouldRegisterGateway` to true for the callback in registerTokenToL2 to succeed bool prev = shouldRegisterGateway; shouldRegisterGateway = true; @@ -103,6 +131,63 @@ contract TestCustomTokenL1 is aeERC20, ICustomToken { } } +contract TestOrbitCustomTokenL1 is TestCustomTokenL1 { + using SafeERC20 for IERC20; + + constructor(address _gateway, address _router) TestCustomTokenL1(_gateway, _router) {} + + function registerTokenOnL2( + address l2CustomTokenAddress, + uint256 maxSubmissionCostForCustomGateway, + uint256 maxSubmissionCostForRouter, + uint256 maxGasForCustomGateway, + uint256 maxGasForRouter, + uint256 gasPriceBid, + uint256 valueForGateway, + uint256 valueForRouter, + address creditBackAddress + ) public payable override { + // we temporarily set `shouldRegisterGateway` to true for the callback in registerTokenToL2 to succeed + bool prev = shouldRegisterGateway; + shouldRegisterGateway = true; + + // transfer fees from user to here, and approve router to use it + { + address inbox = IOrbitGatewayRouter(router).inbox(); + address bridge = address(IInbox(inbox).bridge()); + address nativeToken = IERC20Bridge(bridge).nativeToken(); + + IERC20(nativeToken).safeTransferFrom( + msg.sender, + address(this), + valueForGateway + valueForRouter + ); + IERC20(nativeToken).approve(router, valueForRouter); + IERC20(nativeToken).approve(gateway, valueForGateway); + } + + IL1OrbitCustomGateway(gateway).registerTokenToL2( + l2CustomTokenAddress, + maxGasForCustomGateway, + gasPriceBid, + maxSubmissionCostForCustomGateway, + creditBackAddress, + valueForGateway + ); + + IOrbitGatewayRouter(router).setGateway( + gateway, + maxGasForRouter, + gasPriceBid, + maxSubmissionCostForRouter, + creditBackAddress, + valueForRouter + ); + + shouldRegisterGateway = prev; + } +} + contract MintableTestCustomTokenL1 is L1MintableToken, TestCustomTokenL1 { constructor(address _gateway, address _router) TestCustomTokenL1(_gateway, _router) {} @@ -111,21 +196,16 @@ contract MintableTestCustomTokenL1 is L1MintableToken, TestCustomTokenL1 { _; } - function bridgeMint(address account, uint256 amount) - public - override(L1MintableToken) - onlyGateway - { + function bridgeMint( + address account, + uint256 amount + ) public override(L1MintableToken) onlyGateway { _mint(account, amount); } - function balanceOf(address account) - public - view - virtual - override(TestCustomTokenL1, ICustomToken) - returns (uint256 amount) - { + function balanceOf( + address account + ) public view virtual override(TestCustomTokenL1, ICustomToken) returns (uint256 amount) { return super.balanceOf(account); } @@ -141,20 +221,16 @@ contract MintableTestCustomTokenL1 is L1MintableToken, TestCustomTokenL1 { contract ReverseTestCustomTokenL1 is L1ReverseToken, MintableTestCustomTokenL1 { constructor(address _gateway, address _router) MintableTestCustomTokenL1(_gateway, _router) {} - function bridgeBurn(address account, uint256 amount) - public - override(L1ReverseToken) - onlyGateway - { + function bridgeBurn( + address account, + uint256 amount + ) public override(L1ReverseToken) onlyGateway { _burn(account, amount); } - function balanceOf(address account) - public - view - override(MintableTestCustomTokenL1, ICustomToken) - returns (uint256 amount) - { + function balanceOf( + address account + ) public view override(MintableTestCustomTokenL1, ICustomToken) returns (uint256 amount) { return super.balanceOf(account); } diff --git a/test-foundry/Integration.t.sol b/test-foundry/L1OrbitIntegration.t.sol similarity index 51% rename from test-foundry/Integration.t.sol rename to test-foundry/L1OrbitIntegration.t.sol index 4d9adaa195..151c73afd6 100644 --- a/test-foundry/Integration.t.sol +++ b/test-foundry/L1OrbitIntegration.t.sol @@ -13,7 +13,7 @@ import { L1OrbitCustomGateway } from "contracts/tokenbridge/ethereum/gateway/L1O import { ERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { ERC20PresetMinterPauser } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; - +import { TestOrbitCustomTokenL1 } from "contracts/tokenbridge/test/TestCustomTokenL1.sol"; import { ERC20Inbox } from "lib/nitro-contracts/contracts/src/bridge/ERC20Inbox.sol"; import { ERC20Bridge } from "lib/nitro-contracts/contracts/src/bridge/ERC20Bridge.sol"; import { ERC20PresetFixedSupply } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol"; @@ -36,11 +36,20 @@ contract IntegrationTest is Test { ERC20Bridge public bridge; L1OrbitERC20Gateway public defaultGateway; L1OrbitGatewayRouter public router; - IERC20 public token; + + uint256 private maxSubmissionCost = 0; + uint256 private maxGas = 100000; + uint256 private gasPriceBid = 3; + uint256 private nativeTokenTotalFee; function setUp() public { // deploy token, bridge and inbox - nativeToken = new ERC20PresetFixedSupply("Appchain Token", "App", 100000000, address(this)); + nativeToken = new ERC20PresetFixedSupply( + "Appchain Token", + "App", + 1_000_000 ether, + address(this) + ); inbox = ERC20Inbox(TestUtil.deployProxy(address(new ERC20Inbox()))); bridge = ERC20Bridge(TestUtil.deployProxy(address(new ERC20Bridge()))); @@ -70,47 +79,53 @@ contract IntegrationTest is Test { l2BeaconProxyFactory ); - // token to bridge - token = IERC20(address(new TestERC20())); - - // fund accounts - nativeToken.transfer(user, 1_000_000); - nativeToken.transfer(owner, 1_000_000); - vm.prank(user); - TestERC20(address(token)).mint(); - // vm.deal(owner, 100 ether); - // vm.deal(user, 100 ether); + nativeTokenTotalFee = maxGas * gasPriceBid; } /* solhint-disable func-name-mixedcase */ - function test_depositNative() public { - uint256 depositAmount = 140; + function test_depositNative(uint256 depositAmount) public { + vm.assume(depositAmount < 1_000_000 ether); + nativeToken.transfer(user, depositAmount); + + // snapshot before + uint256 userNativeTokenBalanceBefore = nativeToken.balanceOf(user); + uint256 bridgeNativeTokenBalanceBefore = nativeToken.balanceOf(address(bridge)); + vm.prank(user); - nativeToken.approve(address(bridge), 140); + nativeToken.approve(address(inbox), depositAmount); vm.prank(user); inbox.depositERC20(depositAmount); + + // snapshot before + uint256 userNativeTokenBalanceAfter = nativeToken.balanceOf(user); + uint256 bridgeNativeTokenBalanceAfter = nativeToken.balanceOf(address(bridge)); + + assertEq( + userNativeTokenBalanceBefore - userNativeTokenBalanceAfter, + depositAmount, + "Invalid user native token balance" + ); + + assertEq( + bridgeNativeTokenBalanceAfter - bridgeNativeTokenBalanceBefore, + depositAmount, + "Invalid bridge token balance" + ); } - function test_depositToken() public { + function test_depositToken_DefaultGateway() public { uint256 tokenDepositAmount = 250; - uint256 maxSubmissionCost = 0; - uint256 maxGas = 100000; - uint256 gasPriceBid = 3; - uint256 nativeTokenTotalFee = maxGas * gasPriceBid; - - /// set default gateway - vm.startPrank(owner); - nativeToken.approve(address(router), nativeTokenTotalFee); - router.setDefaultGateway( - address(defaultGateway), - maxGas, - gasPriceBid, - maxSubmissionCost, - nativeTokenTotalFee - ); - assertEq(router.defaultGateway(), address(defaultGateway), "Invalid defaultGateway"); - vm.stopPrank(); + + // token to bridge + IERC20 token = IERC20(address(new TestERC20())); + + // fund account + vm.prank(user); + TestERC20(address(token)).mint(); + + // fund user to be able to pay retryable fees + nativeToken.transfer(user, nativeTokenTotalFee); // snapshot state before uint256 userTokenBalanceBefore = token.balanceOf(user); @@ -119,11 +134,12 @@ contract IntegrationTest is Test { uint256 bridgeNativeTokenBalanceBefore = nativeToken.balanceOf(address(bridge)); { - /// do token deposit vm.startPrank(user); + /// approve token token.approve(address(defaultGateway), tokenDepositAmount); + // approve fees nativeToken.approve(address(defaultGateway), nativeTokenTotalFee); address refundTo = user; @@ -141,7 +157,7 @@ contract IntegrationTest is Test { vm.stopPrank(); } - /// checks + /// check token moved user->gateway, and native token user->bridge { uint256 userTokenBalanceAfter = token.balanceOf(user); uint256 l1GatewayBalanceAfter = token.balanceOf(address(defaultGateway)); @@ -173,4 +189,111 @@ contract IntegrationTest is Test { ); } } + + function test_depositToken_CustomGateway() public { + uint256 tokenDepositAmount = 250; + + ///////// + nativeToken.transfer(user, nativeTokenTotalFee * 3); + + // create + init custom gateway + L1OrbitCustomGateway customL1Gateway = new L1OrbitCustomGateway(); + L1OrbitCustomGateway(address(customL1Gateway)).initialize( + makeAddr("l2Gateway"), + address(router), + address(inbox), + owner + ); + + // create token and register it + TestOrbitCustomTokenL1 customToken = new TestOrbitCustomTokenL1( + address(customL1Gateway), + address(router) + ); + + vm.startPrank(user); + nativeToken.approve(address(customToken), nativeTokenTotalFee * 2); + customToken.registerTokenOnL2( + makeAddr("l2CustomTokenAddress"), + maxSubmissionCost, + maxSubmissionCost, + maxGas, + maxGas, + gasPriceBid, + nativeTokenTotalFee, + nativeTokenTotalFee, + makeAddr("creditbackAddr") + ); + assertEq( + router.l1TokenToGateway(address(customToken)), + address(customL1Gateway), + "Invalid custom gateway" + ); + customToken.mint(); + vm.stopPrank(); + + // snapshot state before + uint256 userTokenBalanceBefore = customToken.balanceOf(user); + uint256 l1GatewayBalanceBefore = customToken.balanceOf(address(customL1Gateway)); + uint256 userNativeTokenBalanceBefore = nativeToken.balanceOf(user); + uint256 bridgeNativeTokenBalanceBefore = nativeToken.balanceOf(address(bridge)); + + /// deposit custom token + { + vm.startPrank(user); + + /// approve token + customToken.approve(address(customL1Gateway), tokenDepositAmount); + + // approve fees + nativeToken.transfer(user, nativeTokenTotalFee); + nativeToken.approve(address(customL1Gateway), nativeTokenTotalFee); + + address refundTo = user; + bytes memory userEncodedData = abi.encode(maxSubmissionCost, "", nativeTokenTotalFee); + router.outboundTransferCustomRefund( + address(customToken), + refundTo, + user, + tokenDepositAmount, + maxGas, + gasPriceBid, + userEncodedData + ); + + vm.stopPrank(); + } + + /// check token moved user->gateway, and native token user->bridge + { + uint256 userTokenBalanceAfter = customToken.balanceOf(user); + uint256 l1GatewayBalanceAfter = customToken.balanceOf(address(customL1Gateway)); + uint256 userNativeTokenBalanceAfter = nativeToken.balanceOf(user); + uint256 bridgeNativeTokenBalanceAfter = nativeToken.balanceOf(address(bridge)); + + assertEq( + userTokenBalanceBefore - userTokenBalanceAfter, + tokenDepositAmount, + "Invalid user token balance" + ); + + assertEq( + l1GatewayBalanceAfter - l1GatewayBalanceBefore, + tokenDepositAmount, + "Invalid default gateway token balance" + ); + + assertEq( + userNativeTokenBalanceBefore - userNativeTokenBalanceAfter, + nativeTokenTotalFee, + "Invalid user native token balance" + ); + + assertEq( + bridgeNativeTokenBalanceAfter - bridgeNativeTokenBalanceBefore, + nativeTokenTotalFee, + "Invalid user native token balance" + ); + } + } } From 9b1371ce68521377b4685d231969483c631e7eac Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 24 May 2023 15:39:58 +0200 Subject: [PATCH 068/163] Finish orbit token bridge deployer scripts --- .gitignore | 3 + files/local/network.json | 50 ---- package.json | 2 +- scripts/local-deployment/genTokenBridge.ts | 25 -- ...yBridge.ts => orbitTokenBridgeDeployer.ts} | 213 ++++++++++++------ scripts/local-deployment/testSetup.ts | 29 +-- 6 files changed, 160 insertions(+), 162 deletions(-) delete mode 100644 files/local/network.json delete mode 100644 scripts/local-deployment/genTokenBridge.ts rename scripts/local-deployment/{deployBridge.ts => orbitTokenBridgeDeployer.ts} (59%) diff --git a/.gitignore b/.gitignore index 153abeb212..10574ac727 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ forge-cache/ #Storage layout test files test/storage/*-old.dot + +# local deployment files +network.json diff --git a/files/local/network.json b/files/local/network.json deleted file mode 100644 index a12303a51f..0000000000 --- a/files/local/network.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "l1Network": { - "blockTime": 10, - "chainID": 1337, - "explorerUrl": "", - "isCustom": true, - "name": "EthLocal", - "partnerChainIDs": [ - 1337 - ], - "isArbitrum": false - }, - "l2Network": { - "chainID": 1337, - "confirmPeriodBlocks": 20, - "ethBridge": { - "bridge": "0xce08c107a607e6ddf58da38dc1efbf9228abe2c4", - "inbox": "0x780eb6fbe92db687ce5e644c66d10d66441c86d2", - "outbox": "0x6E45Bd4B4Cd028521BDDFa11476735341DfD8F33", - "rollup": "0x0bb03f5c44ce2b206364f794bb861f5e28aface3", - "sequencerInbox": "0x164f0489124f125e7b750f276ea83e9961a6d333" - }, - "nativeToken": "0xa6e41ffd769491a42a6e5ce453259b93983a22ef", - "explorerUrl": "", - "isArbitrum": true, - "isCustom": true, - "name": "ArbLocal", - "partnerChainID": 1337, - "retryableLifetimeSeconds": 604800, - "nitroGenesisBlock": 0, - "nitroGenesisL1Block": 0, - "depositTimeout": 900000, - "tokenBridge": { - "l1CustomGateway": "0x1A3Ef0413FdE0bf110A363f25c3fE6b527f3A8d4", - "l1ERC20Gateway": "0x7696e37e86B993aC1CE27feed48Fa154cB8B2EDa", - "l1GatewayRouter": "0xE85035F1145aC49333d105632a0d254E479a75bE", - "l1MultiCall": "", - "l1ProxyAdmin": "0xe7e96cEF8812D2d24ADD2de592b5C786f915f64b", - "l1Weth": "", - "l1WethGateway": "", - "l2CustomGateway": "0xeB0283a324B1E5A22fe6d3295E7c54169c2F95CA", - "l2ERC20Gateway": "0x2cc42F00be0fE77FF5Ba18e6e039f373e62c13F2", - "l2GatewayRouter": "0xe7e8B4930802Ce5909cB2A2b8d2e447837158660", - "l2Multicall": "", - "l2ProxyAdmin": "0xEc6c3dF641BDe740992898f25A780aab35d0062f", - "l2Weth": "", - "l2WethGateway": "" - } - } -} \ No newline at end of file diff --git a/package.json b/package.json index a64ae9fba7..687dab216a 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "test:l2": "hardhat test test/*.l2.ts", "test:unit": "forge test", "test:storage": "./scripts/storage_layout_test.bash", - "test:deploy:tokenbridge": "ts-node ./scripts/local-deployment/genTokenBridge.ts", + "test:deploy:orbit-tokenbridge": "ts-node ./scripts/local-deployment/orbitTokenBridgeDeployer.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", diff --git a/scripts/local-deployment/genTokenBridge.ts b/scripts/local-deployment/genTokenBridge.ts deleted file mode 100644 index eafcac64bb..0000000000 --- a/scripts/local-deployment/genTokenBridge.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ethers } from 'ethers' -import { setupNetworks, config, getSigner } from './testSetup' -import * as fs from 'fs' - -async function main() { - const ethProvider = new ethers.providers.JsonRpcProvider(config.ethUrl) - const arbProvider = new ethers.providers.JsonRpcProvider(config.arbUrl) - - const ethDeployer = getSigner(ethProvider, config.ethKey) - const arbDeployer = getSigner(arbProvider, config.arbKey) - const { l1Network, l2Network } = await setupNetworks( - ethDeployer, - arbDeployer, - config.ethUrl, - config.arbUrl - ) - - fs.writeFileSync( - './files/local/network.json', - JSON.stringify({ l1Network, l2Network }, null, 2) - ) - console.log('network.json updated') -} - -main().then(() => console.log('Done.')) diff --git a/scripts/local-deployment/deployBridge.ts b/scripts/local-deployment/orbitTokenBridgeDeployer.ts similarity index 59% rename from scripts/local-deployment/deployBridge.ts rename to scripts/local-deployment/orbitTokenBridgeDeployer.ts index 1de929a3c5..f76ce18f1c 100644 --- a/scripts/local-deployment/deployBridge.ts +++ b/scripts/local-deployment/orbitTokenBridgeDeployer.ts @@ -1,6 +1,7 @@ -import { Contract, ContractFactory, Signer, constants } from 'ethers' +import { Contract, ContractFactory, Signer, constants, ethers } from 'ethers' import { BeaconProxyFactory__factory, + ERC20__factory, L1OrbitCustomGateway__factory, L1OrbitERC20Gateway__factory, L1OrbitGatewayRouter__factory, @@ -12,28 +13,83 @@ import { TransparentUpgradeableProxy__factory, UpgradeableBeacon__factory, } from '../../build/types' +import { setupOrbitTokenBridge, sleep } from './testSetup' +import * as fs from 'fs' -async function deployContractBehindProxy< - T extends ContractFactory, - U extends Contract ->( - deployer: Signer, - logicFactory: new (deployer: Signer) => T, - proxyAdmin: string, - contractFactory: (address: string, signer: Signer) => U -): Promise { - const logicContract = await new logicFactory(deployer).deploy() - await logicContract.deployed() +/** + * Deploy all the L1 and L2 contracts and do the initialization. + * + * @param l1Signer + * @param l2Signer + * @param inboxAddress + * @param nativeTokenAddress + * @returns + */ +export const deployOrbitTokenBridgeAndInit = async ( + l1Signer: Signer, + l2Signer: Signer, + inboxAddress: string, + nativeTokenAddress: string +) => { + console.log('deploying l1 side') + const l1 = await deployTokenBridgeL1Side(l1Signer) - const proxyContract = await new TransparentUpgradeableProxy__factory( - deployer - ).deploy(logicContract.address, proxyAdmin, '0x') - await proxyContract.deployed() + // fund L2 deployer so contracts can be deployed + await bridgeFundsToL2Deployer(l1Signer, inboxAddress, nativeTokenAddress) - return contractFactory(proxyContract.address, deployer) + console.log('deploying l2 side') + const l2 = await deployTokenBridgeL2Side(l2Signer) + + console.log('initialising L2') + await l2.router.initialize(l1.router.address, l2.standardGateway.address) + await l2.beaconProxyFactory.initialize(l2.beacon.address) + await ( + await l2.standardGateway.initialize( + l1.standardGateway.address, + l2.router.address, + l2.beaconProxyFactory.address + ) + ).wait() + await ( + await l2.customGateway.initialize( + l1.customGateway.address, + l2.router.address + ) + ).wait() + + console.log('initialising L1') + await ( + await l1.router.initialize( + await l1Signer.getAddress(), + l1.standardGateway.address, + constants.AddressZero, + l2.router.address, + inboxAddress + ) + ).wait() + + await ( + await l1.standardGateway.initialize( + l2.standardGateway.address, + l1.router.address, + inboxAddress, + await l2.beaconProxyFactory.cloneableProxyHash(), + l2.beaconProxyFactory.address + ) + ).wait() + await ( + await l1.customGateway.initialize( + l2.customGateway.address, + l1.router.address, + inboxAddress, + await l1Signer.getAddress() + ) + ).wait() + + return { l1, l2 } } -export const deployErc20L1 = async (deployer: Signer) => { +const deployTokenBridgeL1Side = async (deployer: Signer) => { const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() await proxyAdmin.deployed() console.log('proxyAdmin', proxyAdmin.address) @@ -44,6 +100,7 @@ export const deployErc20L1 = async (deployer: Signer) => { proxyAdmin.address, L1OrbitGatewayRouter__factory.connect ) + console.log('router', router.address) const standardGateway = await deployContractBehindProxy( deployer, @@ -51,6 +108,7 @@ export const deployErc20L1 = async (deployer: Signer) => { proxyAdmin.address, L1OrbitERC20Gateway__factory.connect ) + console.log('standardGateway', standardGateway.address) const customGateway = await deployContractBehindProxy( deployer, @@ -58,6 +116,7 @@ export const deployErc20L1 = async (deployer: Signer) => { proxyAdmin.address, L1OrbitCustomGateway__factory.connect ) + console.log('customGateway', standardGateway.address) return { proxyAdmin, @@ -67,7 +126,7 @@ export const deployErc20L1 = async (deployer: Signer) => { } } -export const deployErc20L2 = async (deployer: Signer) => { +const deployTokenBridgeL2Side = async (deployer: Signer) => { const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() await proxyAdmin.deployed() @@ -118,61 +177,83 @@ export const deployErc20L2 = async (deployer: Signer) => { } } -export const deployErc20AndInit = async ( +const bridgeFundsToL2Deployer = async ( l1Signer: Signer, - l2Signer: Signer, - inboxAddress: string + inboxAddress: string, + nativeTokenAddress: string ) => { - console.log('deploying l1') - const l1 = await deployErc20L1(l1Signer) + console.log('fund L2 deployer') - console.log('deploying l2') - const l2 = await deployErc20L2(l2Signer) + const depositAmount = ethers.utils.parseUnits('1000', 'ether') - console.log('initialising L2') - await l2.router.initialize(l1.router.address, l2.standardGateway.address) + // approve tokens to bridge await ( - await l2.standardGateway.initialize( - l1.standardGateway.address, - l2.router.address, - l2.beaconProxyFactory.address - ) - ).wait() - await ( - await l2.customGateway.initialize( - l1.customGateway.address, - l2.router.address + await ERC20__factory.connect(nativeTokenAddress, l1Signer).approve( + inboxAddress, + depositAmount ) ).wait() - console.log('initialising L1') - await ( - await l1.router.initialize( - await l1Signer.getAddress(), - l1.standardGateway.address, - constants.AddressZero, - l2.router.address, - inboxAddress - ) - ).wait() + // bridge it + const orbitInboxAbi = [ + 'function depositERC20(uint256) public returns (uint256)', + ] + const orbitInbox = new Contract(inboxAddress, orbitInboxAbi, l1Signer) + await (await orbitInbox.depositERC20(depositAmount)).wait() + await sleep(30 * 1000) +} - await ( - await l1.standardGateway.initialize( - l2.standardGateway.address, - l1.router.address, - inboxAddress, - await l2.beaconProxyFactory.cloneableProxyHash(), - l2.beaconProxyFactory.address - ) - ).wait() - await ( - await l1.customGateway.initialize( - l2.customGateway.address, - l1.router.address, - inboxAddress, - await l1Signer.getAddress() - ) - ).wait() +async function deployContractBehindProxy< + T extends ContractFactory, + U extends Contract +>( + deployer: Signer, + logicFactory: new (deployer: Signer) => T, + proxyAdmin: string, + contractFactory: (address: string, signer: Signer) => U +): Promise { + const logicContract = await new logicFactory(deployer).deploy() + await logicContract.deployed() - return { l1, l2 } + const proxyContract = await new TransparentUpgradeableProxy__factory( + deployer + ).deploy(logicContract.address, proxyAdmin, '0x') + await proxyContract.deployed() + + return contractFactory(proxyContract.address, deployer) } + +async function main() { + const config = { + arbUrl: 'http://localhost:8547', + ethUrl: 'http://localhost:8545', + } + + const l1Provider = new ethers.providers.JsonRpcProvider(config.ethUrl) + const l2Provider = new ethers.providers.JsonRpcProvider(config.arbUrl) + + const l1DeployerWallet = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + l1Provider + ) + const l2DeployerWallet = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + l2Provider + ) + + const { l1Network, l2Network } = await setupOrbitTokenBridge( + l1DeployerWallet, + l2DeployerWallet, + config.ethUrl, + config.arbUrl + ) + + const NETWORK_FILE = 'network.json' + fs.writeFileSync( + NETWORK_FILE, + JSON.stringify({ l1Network, l2Network }, null, 2) + ) + console.log(NETWORK_FILE + ' updated') +} + +main().then(() => console.log('Done.')) diff --git a/scripts/local-deployment/testSetup.ts b/scripts/local-deployment/testSetup.ts index f9ae0967cc..a77e8c7e22 100644 --- a/scripts/local-deployment/testSetup.ts +++ b/scripts/local-deployment/testSetup.ts @@ -1,21 +1,10 @@ import { JsonRpcProvider } from '@ethersproject/providers' -import dotenv from 'dotenv' import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' import { execSync } from 'child_process' import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' import { Signer, Wallet } from 'ethers' -import { L2GatewayRouter__factory } from '../../build/types' -import { deployErc20AndInit } from './deployBridge' - -dotenv.config() - -export const config = { - arbUrl: process.env['ARB_URL'] as string, - ethUrl: process.env['ETH_URL'] as string, - arbKey: process.env['ARB_KEY'] as string, - ethKey: process.env['ETH_KEY'] as string, -} +import { deployOrbitTokenBridgeAndInit } from './orbitTokenBridgeDeployer' export const getCustomNetworks = async ( l1Url: string, @@ -96,7 +85,7 @@ export const getCustomNetworks = async ( } } -export const setupNetworks = async ( +export const setupOrbitTokenBridge = async ( l1Deployer: Signer, l2Deployer: Signer, l1Url: string, @@ -107,13 +96,13 @@ export const setupNetworks = async ( l2Url ) - new L2GatewayRouter__factory(l1Deployer).deploy() - - const { l1: l1Contracts, l2: l2Contracts } = await deployErc20AndInit( - l1Deployer, - l2Deployer, - coreL2Network.ethBridge.inbox - ) + const { l1: l1Contracts, l2: l2Contracts } = + await deployOrbitTokenBridgeAndInit( + l1Deployer, + l2Deployer, + coreL2Network.ethBridge.inbox, + coreL2Network.nativeToken + ) const l2Network: L2Network = { ...coreL2Network, tokenBridge: { From 03424af37dc257763c910448a5d39316b368e2a8 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 25 May 2023 13:06:53 +0200 Subject: [PATCH 069/163] Add end2end test for token deposit --- scripts/local-deployment/testSetup.ts | 4 +- test-e2e/orbitTokenBridge.ts | 238 ++++++++++++++++++++++++++ 2 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 test-e2e/orbitTokenBridge.ts diff --git a/scripts/local-deployment/testSetup.ts b/scripts/local-deployment/testSetup.ts index a77e8c7e22..18e6774ed0 100644 --- a/scripts/local-deployment/testSetup.ts +++ b/scripts/local-deployment/testSetup.ts @@ -103,7 +103,9 @@ export const setupOrbitTokenBridge = async ( coreL2Network.ethBridge.inbox, coreL2Network.nativeToken ) - const l2Network: L2Network = { + const l2Network: L2Network & { + nativeToken: string + } = { ...coreL2Network, tokenBridge: { l1CustomGateway: l1Contracts.customGateway.address, diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts new file mode 100644 index 0000000000..8add6af81c --- /dev/null +++ b/test-e2e/orbitTokenBridge.ts @@ -0,0 +1,238 @@ +import { + L1Network, + L1ToL2MessageGasEstimator, + L1ToL2MessageStatus, + L1TransactionReceipt, + L2Network, +} from '@arbitrum/sdk' +import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' +import { JsonRpcProvider } from '@ethersproject/providers' +import { expect } from 'chai' +import { ethers, Wallet } from '@arbitrum/sdk/node_modules/ethers' +import { setupOrbitTokenBridge } from '../scripts/local-deployment/testSetup' +import { + ERC20__factory, + L1OrbitERC20Gateway__factory, + L1OrbitGatewayRouter__factory, + TestERC20__factory, +} from '../build/types' +import { defaultAbiCoder } from 'ethers/lib/utils' +import { BigNumber } from 'ethers' + +const config = { + arbUrl: 'http://localhost:8547', + ethUrl: 'http://localhost:8545', +} + +let l1Provider: JsonRpcProvider +let l2Provider: JsonRpcProvider + +let deployerL1Wallet: Wallet +let deployerL2Wallet: Wallet + +let userL1Wallet: Wallet +let userL2Wallet: Wallet + +let _l1Network: L1Network +let _l2Network: L2Network & { nativeToken: string } + +describe('orbitTokenBridge', () => { + // configure orbit token bridge + before(async function () { + l1Provider = new ethers.providers.JsonRpcProvider(config.ethUrl) + l2Provider = new ethers.providers.JsonRpcProvider(config.arbUrl) + + const deployerKey = ethers.utils.sha256( + ethers.utils.toUtf8Bytes('user_l1user') + ) + deployerL1Wallet = new ethers.Wallet(deployerKey, l1Provider) + deployerL2Wallet = new ethers.Wallet(deployerKey, l2Provider) + + console.log('setupOrbitTokenBridge') + const { l1Network, l2Network } = await setupOrbitTokenBridge( + deployerL1Wallet, + deployerL2Wallet, + config.ethUrl, + config.arbUrl + ) + + _l1Network = l1Network + _l2Network = l2Network + + // create user wallets and fund it + const userKey = ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_wallet')) + userL1Wallet = new ethers.Wallet(userKey, l1Provider) + userL2Wallet = new ethers.Wallet(userKey, l2Provider) + console.log('fund userL1Wallet') + await ( + await deployerL1Wallet.sendTransaction({ + to: userL1Wallet.address, + value: ethers.utils.parseEther('1.0'), + }) + ).wait() + }) + + it('should have deployed token bridge contracts', async function () { + // get router as entry point + const l1Router = L1OrbitGatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + l1Provider + ) + + expect((await l1Router.defaultGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1ERC20Gateway.toLowerCase() + ) + // expect((await l1Router.counterpartGateway()).toLowerCase()).to.be.eq( + // _l2Network.tokenBridge.l2ERC20Gateway.toLowerCase() + // ) + }) + + it('can deposit token via default gateway', async function () { + // fund user to be able to pay retryable fees + const nativeToken = ERC20__factory.connect( + _l2Network.nativeToken, + userL1Wallet + ) + await ( + await nativeToken + .connect(deployerL1Wallet) + .transfer(userL1Wallet.address, ethers.utils.parseEther('1000')) + ).wait() + + // create token to be bridged + const tokenFactory = await new TestERC20__factory(userL1Wallet).deploy() + const token = await tokenFactory.deployed() + await (await token.mint()).wait() + + // 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 + ) + + // approve token + const depositAmount = 350 + await ( + await token.approve(_l2Network.tokenBridge.l1ERC20Gateway, depositAmount) + ).wait() + + // calculate retryable params + const maxSubmissionCost = 0 + 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(l2Provider) + 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(l1Provider), + l1Provider + ) + + const gasLimit = retryableParams.gasLimit.mul(40) + const maxFeePerGas = retryableParams.maxFeePerGas + const tokenTotalFeeAmount = gasLimit.mul(maxFeePerGas).mul(2) + + // approve fee amount + await ( + await nativeToken.approve( + _l2Network.tokenBridge.l1ERC20Gateway, + tokenTotalFeeAmount + ) + ).wait() + + // bridge it + const userEncodedData = defaultAbiCoder.encode( + ['uint256', 'bytes', 'uint256'], + [maxSubmissionCost, callhook, tokenTotalFeeAmount] + ) + + const router = L1OrbitGatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + userL1Wallet + ) + + const depositTx = await router.outboundTransferCustomRefund( + token.address, + userL1Wallet.address, + userL2Wallet.address, + depositAmount, + gasLimit, + maxFeePerGas, + userEncodedData + ) + + // wait for L2 msg to be executed + await waitOnL2Msg(depositTx) + + ///// checks + + const l2TokenAddress = await router.calculateL2TokenAddress(token.address) + const l2Token = ERC20__factory.connect(l2TokenAddress, l2Provider) + expect(await l2Token.balanceOf(userL2Wallet.address)).to.be.eq( + depositAmount + ) + + const userTokenBalanceAfter = await token.balanceOf(userL1Wallet.address) + expect(userTokenBalanceBefore.sub(userTokenBalanceAfter)).to.be.eq( + depositAmount + ) + + const gatewayTokenBalanceAfter = await token.balanceOf( + _l2Network.tokenBridge.l1ERC20Gateway + ) + expect(gatewayTokenBalanceAfter.sub(gatewayTokenBalanceBefore)).to.be.eq( + depositAmount + ) + + const userNativeTokenBalanceAfter = await nativeToken.balanceOf( + userL1Wallet.address + ) + console.log('userNativeTokenBalanceAfter', userNativeTokenBalanceAfter) + expect( + userNativeTokenBalanceBefore.sub(userNativeTokenBalanceAfter) + ).to.be.eq(tokenTotalFeeAmount) + + const bridgeNativeTokenBalanceAfter = await nativeToken.balanceOf( + _l2Network.ethBridge.bridge + ) + expect( + bridgeNativeTokenBalanceAfter.sub(bridgeNativeTokenBalanceBefore) + ).to.be.eq(tokenTotalFeeAmount) + }) +}) + +async function waitOnL2Msg(tx: ethers.ContractTransaction) { + const retryableReceipt = await tx.wait() + const l1TxReceipt = new L1TransactionReceipt(retryableReceipt) + const messages = await l1TxReceipt.getL1ToL2Messages(l2Provider) + + // 1 msg expected + const messageResult = await messages[0].waitForStatus() + const status = messageResult.status + expect(status).to.be.eq(L1ToL2MessageStatus.REDEEMED) +} From 16f6575aa6f7f0e1e664090717568e4eb4c1c625 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 25 May 2023 18:12:18 +0200 Subject: [PATCH 070/163] Add withdrawal e2e test --- test-e2e/orbitTokenBridge.ts | 128 ++++++++++++++++++++++++++++++++--- 1 file changed, 118 insertions(+), 10 deletions(-) diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 8add6af81c..37563327cb 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -4,20 +4,28 @@ import { L1ToL2MessageStatus, L1TransactionReceipt, L2Network, + L2TransactionReceipt, } from '@arbitrum/sdk' import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' import { JsonRpcProvider } from '@ethersproject/providers' import { expect } from 'chai' import { ethers, Wallet } from '@arbitrum/sdk/node_modules/ethers' -import { setupOrbitTokenBridge } from '../scripts/local-deployment/testSetup' import { + setupOrbitTokenBridge, + sleep, +} from '../scripts/local-deployment/testSetup' +import { + ERC20, ERC20__factory, L1OrbitERC20Gateway__factory, L1OrbitGatewayRouter__factory, + L2GatewayRouter__factory, + TestERC20, TestERC20__factory, } from '../build/types' import { defaultAbiCoder } from 'ethers/lib/utils' import { BigNumber } from 'ethers' +import { IERC20Inbox__factory } from '../build/types' const config = { arbUrl: 'http://localhost:8547', @@ -36,6 +44,10 @@ let userL2Wallet: Wallet let _l1Network: L1Network let _l2Network: L2Network & { nativeToken: string } +let token: TestERC20 +let l2Token: ERC20 +let nativeToken: ERC20 + describe('orbitTokenBridge', () => { // configure orbit token bridge before(async function () { @@ -63,11 +75,10 @@ describe('orbitTokenBridge', () => { const userKey = ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_wallet')) userL1Wallet = new ethers.Wallet(userKey, l1Provider) userL2Wallet = new ethers.Wallet(userKey, l2Provider) - console.log('fund userL1Wallet') await ( await deployerL1Wallet.sendTransaction({ to: userL1Wallet.address, - value: ethers.utils.parseEther('1.0'), + value: ethers.utils.parseEther('10.0'), }) ).wait() }) @@ -89,10 +100,7 @@ describe('orbitTokenBridge', () => { it('can deposit token via default gateway', async function () { // fund user to be able to pay retryable fees - const nativeToken = ERC20__factory.connect( - _l2Network.nativeToken, - userL1Wallet - ) + nativeToken = ERC20__factory.connect(_l2Network.nativeToken, userL1Wallet) await ( await nativeToken .connect(deployerL1Wallet) @@ -101,7 +109,7 @@ describe('orbitTokenBridge', () => { // create token to be bridged const tokenFactory = await new TestERC20__factory(userL1Wallet).deploy() - const token = await tokenFactory.deployed() + token = await tokenFactory.deployed() await (await token.mint()).wait() // snapshot state before @@ -192,7 +200,7 @@ describe('orbitTokenBridge', () => { ///// checks const l2TokenAddress = await router.calculateL2TokenAddress(token.address) - const l2Token = ERC20__factory.connect(l2TokenAddress, l2Provider) + l2Token = ERC20__factory.connect(l2TokenAddress, l2Provider) expect(await l2Token.balanceOf(userL2Wallet.address)).to.be.eq( depositAmount ) @@ -212,7 +220,6 @@ describe('orbitTokenBridge', () => { const userNativeTokenBalanceAfter = await nativeToken.balanceOf( userL1Wallet.address ) - console.log('userNativeTokenBalanceAfter', userNativeTokenBalanceAfter) expect( userNativeTokenBalanceBefore.sub(userNativeTokenBalanceAfter) ).to.be.eq(tokenTotalFeeAmount) @@ -224,8 +231,109 @@ describe('orbitTokenBridge', () => { bridgeNativeTokenBalanceAfter.sub(bridgeNativeTokenBalanceBefore) ).to.be.eq(tokenTotalFeeAmount) }) + + it('can withdraw token via default gateway', async function () { + // fund userL2Wallet so it can pay for L2 withdraw TX + await depositNativeToL2() + + // snapshot state before + const userL1TokenBalanceBefore = await token.balanceOf(userL1Wallet.address) + const userL2TokenBalanceBefore = await l2Token.balanceOf( + userL2Wallet.address + ) + const l1GatewayTokenBalanceBefore = await token.balanceOf( + _l2Network.tokenBridge.l1ERC20Gateway + ) + const l2TokenSupplyBefore = await l2Token.totalSupply() + + // start withdrawal + const withdrawalAmount = 250 + const l2Router = L2GatewayRouter__factory.connect( + _l2Network.tokenBridge.l2GatewayRouter, + userL2Wallet + ) + const withdrawTx = await l2Router[ + 'outboundTransfer(address,address,uint256,bytes)' + ](token.address, userL1Wallet.address, withdrawalAmount, '0x') + const withdrawReceipt = await withdrawTx.wait() + const l2Receipt = new L2TransactionReceipt(withdrawReceipt) + + // wait until dispute period passes and withdrawal is ready for execution + await sleep(5 * 1000) + + const messages = await l2Receipt.getL2ToL1Messages(userL1Wallet) + const l2ToL1Msg = messages[0] + const timeToWaitMs = 60 * 1000 + await l2ToL1Msg.waitUntilReadyToExecute(l2Provider, timeToWaitMs) + + // execute on L1 + await (await l2ToL1Msg.execute(l2Provider)).wait() + + //// checks + const userL1TokenBalanceAfter = await token.balanceOf(userL1Wallet.address) + expect(userL1TokenBalanceAfter.sub(userL1TokenBalanceBefore)).to.be.eq( + withdrawalAmount + ) + + const userL2TokenBalanceAfter = await l2Token.balanceOf( + userL2Wallet.address + ) + expect(userL2TokenBalanceBefore.sub(userL2TokenBalanceAfter)).to.be.eq( + withdrawalAmount + ) + + const l1GatewayTokenBalanceAfter = await token.balanceOf( + _l2Network.tokenBridge.l1ERC20Gateway + ) + expect( + l1GatewayTokenBalanceBefore.sub(l1GatewayTokenBalanceAfter) + ).to.be.eq(withdrawalAmount) + + const l2TokenSupplyAfter = await l2Token.totalSupply() + expect(l2TokenSupplyBefore.sub(l2TokenSupplyAfter)).to.be.eq( + withdrawalAmount + ) + }) }) +/** + * helper function to fund user wallet on L2 + */ +async function depositNativeToL2() { + /// deposit tokens + const amountToDeposit = ethers.utils.parseEther('2.0') + await ( + await nativeToken + .connect(userL1Wallet) + .approve(_l2Network.ethBridge.inbox, amountToDeposit) + ).wait() + + const depositFuncSig = { + name: 'depositERC20', + type: 'function', + stateMutability: 'nonpayable', + inputs: [ + { + name: 'amount', + type: 'uint256', + }, + ], + } + const inbox = new ethers.Contract( + _l2Network.ethBridge.inbox, + [depositFuncSig], + userL1Wallet + ) + + const depositTx = await inbox.depositERC20(amountToDeposit) + + // wait for deposit to be processed + const depositRec = await L1TransactionReceipt.monkeyPatchEthDepositWait( + depositTx + ).wait() + await depositRec.waitForL2(l2Provider) +} + async function waitOnL2Msg(tx: ethers.ContractTransaction) { const retryableReceipt = await tx.wait() const l1TxReceipt = new L1TransactionReceipt(retryableReceipt) From 44ec12017445187d8c3611bc9dd9bf05a659aea0 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 25 May 2023 18:24:59 +0200 Subject: [PATCH 071/163] Decrease retry period --- test-e2e/orbitTokenBridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 37563327cb..08b64579ef 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -263,7 +263,7 @@ describe('orbitTokenBridge', () => { const messages = await l2Receipt.getL2ToL1Messages(userL1Wallet) const l2ToL1Msg = messages[0] - const timeToWaitMs = 60 * 1000 + const timeToWaitMs = 1000 await l2ToL1Msg.waitUntilReadyToExecute(l2Provider, timeToWaitMs) // execute on L1 From feda0f7354cf0761dc4207cadbe5e053f2409337 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 29 May 2023 12:51:04 +0200 Subject: [PATCH 072/163] Use library, formatting --- .solhint.json | 2 +- .../ethereum/gateway/L1GatewayRouter.sol | 4 +++- test-foundry/L1ArbitrumExtendedGateway.t.sol | 22 ++++++++++++------- test-foundry/L1OrbitCustomGateway.t.sol | 9 +++++--- test-foundry/L1OrbitERC20Gateway.t.sol | 9 +++++--- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/.solhint.json b/.solhint.json index f6b6734c51..d2c46a0f97 100644 --- a/.solhint.json +++ b/.solhint.json @@ -4,6 +4,6 @@ "rules": { "mark-callable-contracts": "none", "prettier/prettier": "error", - "compiler-version": ["error", "^0.8.17"] + "compiler-version": ["error", "^0.8.0"] } } diff --git a/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol b/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol index d239a96883..f5aef49d97 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol @@ -39,6 +39,8 @@ contract L1GatewayRouter is ERC165, IL1GatewayRouter { + using Address for address; + address public override owner; address public override inbox; @@ -177,7 +179,7 @@ contract L1GatewayRouter is "NOT_ARB_ENABLED" ); - require(Address.isContract(_gateway), "NOT_TO_CONTRACT"); + require(_gateway.isContract(), "NOT_TO_CONTRACT"); address currGateway = getGateway(msg.sender); if (currGateway != address(0) && currGateway != defaultGateway) { diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol index 287927a4d9..48b822987f 100644 --- a/test-foundry/L1ArbitrumExtendedGateway.t.sol +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -89,7 +89,11 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { l1Gateway.finalizeInboundTransfer(address(token), user, user, 100, ""); } - function test_getExternalCall(uint256 exitNum, address dest, bytes memory data) public { + function test_getExternalCall( + uint256 exitNum, + address dest, + bytes memory data + ) public { (address target, bytes memory extData) = L1ArbitrumExtendedGateway(address(l1Gateway)) .getExternalCall(exitNum, dest, data); @@ -263,10 +267,9 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { assertEq(exitData.length, 0, "Invalid exitData"); } - function test_transferExitAndCall_NonEmptyData( - uint256 exitNum, - address initialDestination - ) public { + function test_transferExitAndCall_NonEmptyData(uint256 exitNum, address initialDestination) + public + { bytes memory newData; bytes memory data = abi.encode("fun()"); address newDestination = address(new TestExitReceiver()); @@ -426,9 +429,12 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { //// // Helper functions //// - function buildRouterEncodedData( - bytes memory callHookData - ) internal view virtual returns (bytes memory) { + function buildRouterEncodedData(bytes memory callHookData) + internal + view + virtual + returns (bytes memory) + { bytes memory userEncodedData = abi.encode(maxSubmissionCost, callHookData); bytes memory routerEncodedData = abi.encode(user, userEncodedData); diff --git a/test-foundry/L1OrbitCustomGateway.t.sol b/test-foundry/L1OrbitCustomGateway.t.sol index 45a4180f7d..20093a8db6 100644 --- a/test-foundry/L1OrbitCustomGateway.t.sol +++ b/test-foundry/L1OrbitCustomGateway.t.sol @@ -577,9 +577,12 @@ contract L1OrbitCustomGatewayTest is L1CustomGatewayTest { /// // Helper functions /// - function buildRouterEncodedData( - bytes memory callHookData - ) internal view override returns (bytes memory) { + function buildRouterEncodedData(bytes memory callHookData) + internal + view + override + returns (bytes memory) + { bytes memory userEncodedData = abi.encode( maxSubmissionCost, callHookData, diff --git a/test-foundry/L1OrbitERC20Gateway.t.sol b/test-foundry/L1OrbitERC20Gateway.t.sol index b2a85662a3..ecd7a78291 100644 --- a/test-foundry/L1OrbitERC20Gateway.t.sol +++ b/test-foundry/L1OrbitERC20Gateway.t.sol @@ -200,9 +200,12 @@ contract L1OrbitERC20GatewayTest is L1ERC20GatewayTest { //// // Helper functions //// - function buildRouterEncodedData( - bytes memory callHookData - ) internal view override returns (bytes memory) { + function buildRouterEncodedData(bytes memory callHookData) + internal + view + override + returns (bytes memory) + { bytes memory userEncodedData = abi.encode( maxSubmissionCost, callHookData, From f0f78ff7ba7c2e85fcd49f7652539478083ec7ed Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 1 Jun 2023 12:42:42 +0200 Subject: [PATCH 073/163] Use feature-orbit-bridge branch of nitro-contracts --- .gitmodules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 3877275564..e19917d6cd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,5 +3,5 @@ url = https://github.com/foundry-rs/forge-std [submodule "lib/nitro-contracts"] path = lib/nitro-contracts - url = git@github.com:OffchainLabs/nitro-private.git - branch = develop + url = git@github.com:OffchainLabs/nitro-contracts.git + branch = feature-orbit-bridge From 77dfa6f50a20a95b33ac8bc59a74b3dedda6dbb3 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 1 Jun 2023 13:51:08 +0200 Subject: [PATCH 074/163] Update path --- test-foundry/L1OrbitIntegration.t.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test-foundry/L1OrbitIntegration.t.sol b/test-foundry/L1OrbitIntegration.t.sol index 151c73afd6..985856e8c1 100644 --- a/test-foundry/L1OrbitIntegration.t.sol +++ b/test-foundry/L1OrbitIntegration.t.sol @@ -14,11 +14,11 @@ import { ERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { ERC20PresetMinterPauser } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; import { TestERC20 } from "contracts/tokenbridge/test/TestERC20.sol"; import { TestOrbitCustomTokenL1 } from "contracts/tokenbridge/test/TestCustomTokenL1.sol"; -import { ERC20Inbox } from "lib/nitro-contracts/contracts/src/bridge/ERC20Inbox.sol"; -import { ERC20Bridge } from "lib/nitro-contracts/contracts/src/bridge/ERC20Bridge.sol"; +import { ERC20Inbox } from "lib/nitro-contracts/src/bridge/ERC20Inbox.sol"; +import { ERC20Bridge } from "lib/nitro-contracts/src/bridge/ERC20Bridge.sol"; import { ERC20PresetFixedSupply } from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol"; -import { IOwnable } from "lib/nitro-contracts/contracts/src/bridge/IOwnable.sol"; -import { ISequencerInbox } from "lib/nitro-contracts/contracts/src/bridge/ISequencerInbox.sol"; +import { IOwnable } from "lib/nitro-contracts/src/bridge/IOwnable.sol"; +import { ISequencerInbox } from "lib/nitro-contracts/src/bridge/ISequencerInbox.sol"; import "./util/TestUtil.sol"; contract IntegrationTest is Test { From a0717862f007a8361859a89479047582e89de8f6 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 1 Jun 2023 13:57:11 +0200 Subject: [PATCH 075/163] Update submodule commits --- lib/nitro-contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nitro-contracts b/lib/nitro-contracts index 2497d70a32..f8fad6fd6a 160000 --- a/lib/nitro-contracts +++ b/lib/nitro-contracts @@ -1 +1 @@ -Subproject commit 2497d70a322c05309f11267fd7913e596ac12ce9 +Subproject commit f8fad6fd6a79a45a1a6c8aa3629fd9b82522fa1d From 63f3bb1ece2904e2cfc2d4f877de33fc625acdda Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Sun, 4 Jun 2023 18:34:50 +0200 Subject: [PATCH 076/163] Add yarn action for running e2e Orbit test in local test env --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 901f79cf73..b0ed9fc4d1 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "test:l1": "hardhat test test/*.l1.ts", "test:l2": "hardhat test test/*.l2.ts", "test:unit": "forge test", + "test:e2e:local-env": "yarn hardhat test test-e2e/*", "test:storage": "./scripts/storage_layout_test.bash", "typechain": "hardhat typechain", "deploy:tokenbridge": "hardhat run scripts/deploy_token_bridge_l1.ts --network mainnet", From 5e98fa6e839768380a4030801e012d4b47d3d372 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 26 Jun 2023 16:45:22 +0200 Subject: [PATCH 077/163] Add TypeScript deployer for token bridge --- package.json | 2 + .../local-deployment/tokenBridgeDeployer.ts | 392 +++ yarn.lock | 2478 +++++++---------- 3 files changed, 1476 insertions(+), 1396 deletions(-) create mode 100644 scripts/local-deployment/tokenBridgeDeployer.ts diff --git a/package.json b/package.json index 36e6bdbaea..618025c558 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "test:l1": "hardhat test test/*.l1.ts", "test:l2": "hardhat test test/*.l2.ts", "test:storage": "./scripts/storage_layout_test.bash", + "test:deploy:tokenbridge": "ts-node ./scripts/local-deployment/tokenBridgeDeployer.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", @@ -32,6 +33,7 @@ ], "dependencies": { "@arbitrum/nitro-contracts": "^1.0.0-beta.8", + "@arbitrum/sdk": "^3.1.5", "@openzeppelin/contracts": "4.8.3", "@openzeppelin/contracts-upgradeable": "4.8.3" }, diff --git a/scripts/local-deployment/tokenBridgeDeployer.ts b/scripts/local-deployment/tokenBridgeDeployer.ts new file mode 100644 index 0000000000..b52a465b59 --- /dev/null +++ b/scripts/local-deployment/tokenBridgeDeployer.ts @@ -0,0 +1,392 @@ +import { + Contract, + ContractFactory, + Signer, + Wallet, + constants, + ethers, +} from 'ethers' +import { + BeaconProxyFactory__factory, + L1CustomGateway__factory, + L1ERC20Gateway__factory, + L1GatewayRouter__factory, + L2CustomGateway__factory, + L2ERC20Gateway__factory, + L2GatewayRouter__factory, + ProxyAdmin__factory, + StandardArbERC20__factory, + TransparentUpgradeableProxy__factory, + UpgradeableBeacon__factory, +} from '../../build/types' +import { JsonRpcProvider } from '@ethersproject/providers' +import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' +import { execSync } from 'child_process' +import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' +import * as fs from 'fs' + +export const setupTokenBridge = async ( + l1Deployer: Signer, + l2Deployer: Signer, + l1Url: string, + l2Url: string +) => { + const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( + l1Url, + l2Url + ) + + const { l1: l1Contracts, l2: l2Contracts } = await deployTokenBridgeAndInit( + l1Deployer, + l2Deployer, + coreL2Network.ethBridge.inbox + ) + const l2Network: L2Network = { + ...coreL2Network, + tokenBridge: { + l1CustomGateway: l1Contracts.customGateway.address, + l1ERC20Gateway: l1Contracts.standardGateway.address, + l1GatewayRouter: l1Contracts.router.address, + l1MultiCall: '', + l1ProxyAdmin: l1Contracts.proxyAdmin.address, + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: l2Contracts.customGateway.address, + l2ERC20Gateway: l2Contracts.standardGateway.address, + l2GatewayRouter: l2Contracts.router.address, + l2Multicall: '', + l2ProxyAdmin: l2Contracts.proxyAdmin.address, + l2Weth: '', + l2WethGateway: '', + }, + } + + addCustomNetwork({ + customL1Network: l1Network, + customL2Network: l2Network, + }) + + return { + l1Network, + l2Network, + } +} + +/** + * Deploy all the L1 and L2 contracts and do the initialization. + * + * @param l1Signer + * @param l2Signer + * @param inboxAddress + * @returns + */ +export const deployTokenBridgeAndInit = async ( + l1Signer: Signer, + l2Signer: Signer, + inboxAddress: string +) => { + console.log('deploying l1 side') + const l1 = await deployTokenBridgeL1Side(l1Signer) + + // fund L2 deployer so contracts can be deployed + await bridgeFundsToL2Deployer(l1Signer, inboxAddress) + + console.log('deploying l2 side') + const l2 = await deployTokenBridgeL2Side(l2Signer) + + console.log('initialising L2') + await l2.router.initialize(l1.router.address, l2.standardGateway.address) + await l2.beaconProxyFactory.initialize(l2.beacon.address) + await ( + await l2.standardGateway.initialize( + l1.standardGateway.address, + l2.router.address, + l2.beaconProxyFactory.address + ) + ).wait() + await ( + await l2.customGateway.initialize( + l1.customGateway.address, + l2.router.address + ) + ).wait() + + console.log('initialising L1') + await ( + await l1.router.initialize( + await l1Signer.getAddress(), + l1.standardGateway.address, + constants.AddressZero, + l2.router.address, + inboxAddress + ) + ).wait() + + await ( + await l1.standardGateway.initialize( + l2.standardGateway.address, + l1.router.address, + inboxAddress, + await l2.beaconProxyFactory.cloneableProxyHash(), + l2.beaconProxyFactory.address + ) + ).wait() + await ( + await l1.customGateway.initialize( + l2.customGateway.address, + l1.router.address, + inboxAddress, + await l1Signer.getAddress() + ) + ).wait() + + return { l1, l2 } +} + +const deployTokenBridgeL1Side = async (deployer: Signer) => { + const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() + await proxyAdmin.deployed() + console.log('proxyAdmin', proxyAdmin.address) + + const router = await deployContractBehindProxy( + deployer, + L1GatewayRouter__factory, + proxyAdmin.address, + L1GatewayRouter__factory.connect + ) + console.log('router', router.address) + + const standardGateway = await deployContractBehindProxy( + deployer, + L1ERC20Gateway__factory, + proxyAdmin.address, + L1ERC20Gateway__factory.connect + ) + console.log('standardGateway', standardGateway.address) + + const customGateway = await deployContractBehindProxy( + deployer, + L1CustomGateway__factory, + proxyAdmin.address, + L1CustomGateway__factory.connect + ) + console.log('customGateway', standardGateway.address) + + return { + proxyAdmin, + router, + standardGateway, + customGateway, + } +} + +const deployTokenBridgeL2Side = async (deployer: Signer) => { + const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() + await proxyAdmin.deployed() + + const router = await deployContractBehindProxy( + deployer, + L2GatewayRouter__factory, + proxyAdmin.address, + L2GatewayRouter__factory.connect + ) + + const standardGateway = await deployContractBehindProxy( + deployer, + L2ERC20Gateway__factory, + proxyAdmin.address, + L2ERC20Gateway__factory.connect + ) + + const customGateway = await deployContractBehindProxy( + deployer, + L2CustomGateway__factory, + proxyAdmin.address, + L2CustomGateway__factory.connect + ) + + const standardArbERC20 = await new StandardArbERC20__factory( + deployer + ).deploy() + await standardArbERC20.deployed() + + const beacon = await new UpgradeableBeacon__factory(deployer).deploy( + standardArbERC20.address + ) + await beacon.deployed() + + const beaconProxyFactory = await new BeaconProxyFactory__factory( + deployer + ).deploy() + await beaconProxyFactory.deployed() + + return { + proxyAdmin, + router, + standardGateway, + customGateway, + standardArbERC20, + beacon, + beaconProxyFactory, + } +} + +const bridgeFundsToL2Deployer = async ( + l1Signer: Signer, + inboxAddress: string +) => { + console.log('fund L2 deployer') + + const depositAmount = ethers.utils.parseUnits('3', 'ether') + + // bridge it + const InboxAbi = ['function depositEth() public payable returns (uint256)'] + const Inbox = new Contract(inboxAddress, InboxAbi, l1Signer) + await (await Inbox.depositEth({ value: depositAmount })).wait() + await sleep(30 * 1000) +} + +async function deployContractBehindProxy< + T extends ContractFactory, + U extends Contract +>( + deployer: Signer, + logicFactory: new (deployer: Signer) => T, + proxyAdmin: string, + contractFactory: (address: string, signer: Signer) => U +): Promise { + const logicContract = await new logicFactory(deployer).deploy() + await logicContract.deployed() + + const proxyContract = await new TransparentUpgradeableProxy__factory( + deployer + ).deploy(logicContract.address, proxyAdmin, '0x') + await proxyContract.deployed() + + return contractFactory(proxyContract.address, deployer) +} + +export const getLocalNetworks = async ( + l1Url: string, + l2Url: string +): Promise<{ + l1Network: L1Network + l2Network: Omit +}> => { + const l1Provider = new JsonRpcProvider(l1Url) + const l2Provider = new JsonRpcProvider(l2Url) + let deploymentData: string + try { + deploymentData = execSync( + 'docker exec nitro_testnode_sequencer_1 cat /config/deployment.json' + ).toString() + } catch (e) { + deploymentData = execSync( + 'docker exec nitro-testnode-sequencer-1 cat /config/deployment.json' + ).toString() + } + const parsedDeploymentData = JSON.parse(deploymentData) as { + bridge: string + inbox: string + ['sequencer-inbox']: string + rollup: string + } + + const rollup = RollupAdminLogic__factory.connect( + parsedDeploymentData.rollup, + l1Provider + ) + const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() + + const bridge = Bridge__factory.connect( + parsedDeploymentData.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 = { + chainID: l2NetworkInfo.chainId, + confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), + ethBridge: { + bridge: parsedDeploymentData.bridge, + inbox: parsedDeploymentData.inbox, + outbox: outboxAddr, + rollup: parsedDeploymentData.rollup, + sequencerInbox: parsedDeploymentData['sequencer-inbox'], + }, + explorerUrl: '', + isArbitrum: true, + isCustom: true, + name: 'ArbLocal', + partnerChainID: l1NetworkInfo.chainId, + retryableLifetimeSeconds: 7 * 24 * 60 * 60, + nitroGenesisBlock: 0, + nitroGenesisL1Block: 0, + depositTimeout: 900000, + } + return { + l1Network, + l2Network, + } +} + +export const getSigner = (provider: JsonRpcProvider, key?: string) => { + if (!key && !provider) + throw new Error('Provide at least one of key or provider.') + if (key) return new Wallet(key).connect(provider) + else return provider.getSigner(0) +} + +export function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)) +} + +async function main() { + const config = { + arbUrl: 'http://localhost:8547', + ethUrl: 'http://localhost:8545', + } + + const l1Provider = new ethers.providers.JsonRpcProvider(config.ethUrl) + const l2Provider = new ethers.providers.JsonRpcProvider(config.arbUrl) + + const l1DeployerWallet = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + l1Provider + ) + const l2DeployerWallet = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + l2Provider + ) + + const { l1Network, l2Network } = await setupTokenBridge( + l1DeployerWallet, + l2DeployerWallet, + config.ethUrl, + config.arbUrl + ) + + const NETWORK_FILE = 'network.json' + fs.writeFileSync( + NETWORK_FILE, + JSON.stringify({ l1Network, l2Network }, null, 2) + ) + console.log(NETWORK_FILE + ' updated') +} + +main().then(() => console.log('Done.')) diff --git a/yarn.lock b/yarn.lock index 5eef3e8328..ecc70a5ed3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8,13 +8,25 @@ integrity sha512-20Pk2Z98fbPLkECcrZSJszKos/OgtvJJR3NcbVfgCJ6EQjDNzW2P1BKqImOz3tJ952dvO2DWEhcLhQ1Wz1e9ng== "@arbitrum/nitro-contracts@^1.0.0-beta.8": - version "1.0.0-beta.8" - resolved "https://registry.yarnpkg.com/@arbitrum/nitro-contracts/-/nitro-contracts-1.0.0-beta.8.tgz#56554091b466ea1539c11691c60835625f6675e5" - integrity sha512-idzrJ/yGbcVUaqm45kFzV157B7V8W05G0cyMZazNhkWs39zO/moVwjMUCJpQ/SGW4OlOQggI8Xuw4xfocno7Xg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/@arbitrum/nitro-contracts/-/nitro-contracts-1.0.2.tgz#c73dce72b8f969a5909d5aaef6da80681c667475" + integrity sha512-Y+cXIQNsy9UNANnFrDGKhHzNmOWttxpXP0/uJFTRmS+rgS4ozlr81/UmBo3tX6uWjziDtquhYRuG3wx17talOQ== dependencies: "@openzeppelin/contracts" "4.5.0" "@openzeppelin/contracts-upgradeable" "4.5.2" - hardhat "^2.6.6" + patch-package "^6.4.7" + optionalDependencies: + sol2uml "2.2.0" + +"@arbitrum/sdk@^3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.5.tgz#ef5d99d60fa63a981c14136ee642e4bb00b2b185" + integrity sha512-IQdu3wr0xtC2jPokosjd+DAKcRO3Hl+C6sFdfpik5KJYcGP5YzLKpxknxusE2kHxkR1AMaLmXvwAf52rcflHHA== + dependencies: + "@ethersproject/address" "^5.0.8" + "@ethersproject/bignumber" "^5.1.1" + "@ethersproject/bytes" "^5.0.8" + ethers "^5.1.0" "@babel/code-frame@7.12.11": version "7.12.11" @@ -24,23 +36,23 @@ "@babel/highlight" "^7.10.4" "@babel/code-frame@^7.0.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" + integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.22.5" -"@babel/helper-validator-identifier@^7.18.6": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== -"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== +"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" + integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== dependencies: - "@babel/helper-validator-identifier" "^7.18.6" + "@babel/helper-validator-identifier" "^7.22.5" chalk "^2.0.0" js-tokens "^4.0.0" @@ -67,6 +79,13 @@ resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + "@eslint/eslintrc@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" @@ -159,6 +178,14 @@ lru-cache "^5.1.1" semaphore-async-await "^1.5.1" +"@ethereumjs/common@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268" + integrity sha512-DEHjW6e38o+JmB/NO3GZBpW4lpaiBpkFgXF6jLcJ6gETBYpEyaA5nTimsWBUJR3Vmtm/didUEbNjajskugZORg== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.1" + "@ethereumjs/common@^2.5.0", "@ethereumjs/common@^2.6.4", "@ethereumjs/common@^2.6.5": version "2.6.5" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30" @@ -178,6 +205,14 @@ ethereumjs-util "^7.1.1" miller-rabin "^4.0.0" +"@ethereumjs/tx@3.3.2": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.2.tgz#348d4624bf248aaab6c44fec2ae67265efe3db00" + integrity sha512-6AaJhwg4ucmwTvw/1qLaZUX5miWrwZ4nLOUsKyb/HtzS3BMw/CasKhdi1ims9mBKeK9sOJCH4qGKOBGyJCeeog== + dependencies: + "@ethereumjs/common" "^2.5.0" + ethereumjs-util "^7.1.2" + "@ethereumjs/tx@^3.3.2", "@ethereumjs/tx@^3.5.1", "@ethereumjs/tx@^3.5.2": version "3.5.2" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.5.2.tgz#197b9b6299582ad84f9527ca961466fce2296c1c" @@ -258,7 +293,7 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.8", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -284,7 +319,7 @@ "@ethersproject/bytes" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.7.0": +"@ethersproject/bignumber@5.7.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.1.1", "@ethersproject/bignumber@^5.4.1", "@ethersproject/bignumber@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== @@ -293,7 +328,7 @@ "@ethersproject/logger" "^5.7.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.7.0": +"@ethersproject/bytes@5.7.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.8", "@ethersproject/bytes@^5.4.0", "@ethersproject/bytes@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== @@ -410,33 +445,7 @@ dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.7.1", "@ethersproject/providers@^5.4.4": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.1.tgz#b0799b616d5579cd1067a8ebf1fc1ec74c1e122c" - integrity sha512-vZveG/DLyo+wk4Ga1yx6jSEHrLPgmTt+dFv0dv8URpVCRf0jVhalps1jq/emN/oXnMRsC7cQgAF32DcXLL7BPQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/providers@5.7.2": +"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.4.4": version "5.7.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== @@ -602,14 +611,14 @@ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== "@jridgewell/resolve-uri@^3.0.3": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + version "3.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -630,20 +639,15 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" -"@noble/hashes@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" - integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== - -"@noble/hashes@~1.1.1": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.3.tgz#360afc77610e0a61f3417e497dcf36862e4f8111" - integrity sha512-CE0FCR57H2acVI5UOzIGSSIYxZ6v/HOhDR0Ro9VLyhnzLwx0o8W1mmgaqlEUx4049qJDlIBRztv5k+MM8vbO3A== +"@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== -"@noble/secp256k1@1.6.3", "@noble/secp256k1@~1.6.0": - version "1.6.3" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.3.tgz#7eed12d9f4404b416999d0c87686836c4c5c9b94" - integrity sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ== +"@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -666,239 +670,38 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/ethereumjs-block@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz#fdd5c045e7baa5169abeed0e1202bf94e4481c49" - integrity sha512-bk8uP8VuexLgyIZAHExH1QEovqx0Lzhc9Ntm63nCRKLHXIZkobaFaeCVwTESV7YkPKUk7NiK11s8ryed4CS9yA== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-blockchain@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz#1a8c243a46d4d3691631f139bfb3a4a157187b0c" - integrity sha512-pLFEoea6MWd81QQYSReLlLfH7N9v7lH66JC/NMPN848ySPPQA5renWnE7wPByfQFzNrPBuDDRFFULMDmj1C0xw== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-ethash" "^2.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - abstract-level "^1.0.3" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - level "^8.0.0" - lru-cache "^5.1.1" - memory-level "^1.0.0" - -"@nomicfoundation/ethereumjs-common@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz#f6bcc7753994555e49ab3aa517fc8bcf89c280b9" - integrity sha512-WS7qSshQfxoZOpHG/XqlHEGRG1zmyjYrvmATvc4c62+gZXgre1ymYP8ZNgx/3FyZY0TWe9OjFlKOfLqmgOeYwA== - dependencies: - "@nomicfoundation/ethereumjs-util" "^8.0.0" - crc-32 "^1.2.0" - -"@nomicfoundation/ethereumjs-ethash@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz#11539c32fe0990e1122ff987d1b84cfa34774e81" - integrity sha512-WpDvnRncfDUuXdsAXlI4lXbqUDOA+adYRQaEezIkxqDkc+LDyYDbd/xairmY98GnQzo1zIqsIL6GB5MoMSJDew== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - abstract-level "^1.0.3" - bigint-crypto-utils "^3.0.23" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-evm@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz#99cd173c03b59107c156a69c5e215409098a370b" - integrity sha512-hVS6qRo3V1PLKCO210UfcEQHvlG7GqR8iFzp0yyjTg2TmJQizcChKgWo8KFsdMw6AyoLgLhHGHw4HdlP8a4i+Q== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@types/async-eventemitter" "^0.2.1" - async-eventemitter "^0.2.4" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz#d9a9c5f0f10310c8849b6525101de455a53e771d" - integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw== - -"@nomicfoundation/ethereumjs-statemanager@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz#14a9d4e1c828230368f7ab520c144c34d8721e4b" - integrity sha512-jCtqFjcd2QejtuAMjQzbil/4NHf5aAWxUc+CvS0JclQpl+7M0bxMofR2AJdtz+P3u0ke2euhYREDiE7iSO31vQ== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - functional-red-black-tree "^1.0.1" - -"@nomicfoundation/ethereumjs-trie@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz#dcfbe3be53a94bc061c9767a396c16702bc2f5b7" - integrity sha512-LIj5XdE+s+t6WSuq/ttegJzZ1vliwg6wlb+Y9f4RlBpuK35B9K02bO7xU+E6Rgg9RGptkWd6TVLdedTI4eNc2A== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - ethereum-cryptography "0.1.3" - readable-stream "^3.6.0" - -"@nomicfoundation/ethereumjs-tx@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz#59dc7452b0862b30342966f7052ab9a1f7802f52" - integrity sha512-Gg3Lir2lNUck43Kp/3x6TfBNwcWC9Z1wYue9Nz3v4xjdcv6oDW9QSMJxqsKw9QEGoBBZ+gqwpW7+F05/rs/g1w== - dependencies: - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-util@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz#deb2b15d2c308a731e82977aefc4e61ca0ece6c5" - integrity sha512-2emi0NJ/HmTG+CGY58fa+DQuAoroFeSH9gKu9O6JnwTtlzJtgfTixuoOqLEgyyzZVvwfIpRueuePb8TonL1y+A== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-vm@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz#2bb50d332bf41790b01a3767ffec3987585d1de6" - integrity sha512-JMPxvPQ3fzD063Sg3Tp+UdwUkVxMoo1uML6KSzFhMH3hoQi/LMuXBoEHAoW83/vyNS9BxEe6jm6LmT5xdeEJ6w== - dependencies: - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-evm" "^1.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@types/async-eventemitter" "^0.2.1" - async-eventemitter "^0.2.4" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - functional-red-black-tree "^1.0.1" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.0.tgz#83a7367342bd053a76d04bbcf4f373fef07cf760" - integrity sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw== - -"@nomicfoundation/solidity-analyzer-darwin-x64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.0.tgz#1225f7da647ae1ad25a87125664704ecc0af6ccc" - integrity sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA== - -"@nomicfoundation/solidity-analyzer-freebsd-x64@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.0.tgz#dbc052dcdfd50ae50fd5ae1788b69b4e0fa40040" - integrity sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg== - -"@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.0.tgz#e6b2eea633995b557e74e881d2a43eab4760903d" - integrity sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ== - -"@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.0.tgz#af81107f5afa794f19988a368647727806e18dc4" - integrity sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w== - -"@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.0.tgz#6877e1da1a06a9f08446070ab6e0a5347109f868" - integrity sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw== - -"@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.0.tgz#bb6cd83a0c259eccef4183796b6329a66cf7ebd9" - integrity sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg== - -"@nomicfoundation/solidity-analyzer-win32-arm64-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.0.tgz#9d4bca1cc9a1333fde985675083b0b7d165f6076" - integrity sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw== - -"@nomicfoundation/solidity-analyzer-win32-ia32-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.0.tgz#0db5bfc6aa952bea4098d8d2c8947b4e5c4337ee" - integrity sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw== - -"@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.0.tgz#2e0f39a2924dcd77db6b419828595e984fabcb33" - integrity sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA== - -"@nomicfoundation/solidity-analyzer@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.0.tgz#e5ddc43ad5c0aab96e5054520d8e16212e125f50" - integrity sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg== - optionalDependencies: - "@nomicfoundation/solidity-analyzer-darwin-arm64" "0.1.0" - "@nomicfoundation/solidity-analyzer-darwin-x64" "0.1.0" - "@nomicfoundation/solidity-analyzer-freebsd-x64" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-arm64-musl" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-x64-gnu" "0.1.0" - "@nomicfoundation/solidity-analyzer-linux-x64-musl" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc" "0.1.0" - "@nomicfoundation/solidity-analyzer-win32-x64-msvc" "0.1.0" - "@nomiclabs/hardhat-ethers@^2.0.1", "@nomiclabs/hardhat-ethers@^2.0.2": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.0.tgz#f55ace2752d0effcf583e754960e9fa89fbe12cd" - integrity sha512-kKCW7xawuD/lw69Yr1yqUUrF0IKmnLNGf+pTVbJ/ctHaRcPrwKI0EPkO1RNXBHlOOZkv6v4DK2PPvq0lL2ykig== + version "2.2.3" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" + integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== "@nomiclabs/hardhat-etherscan@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.1.tgz#471590f25c8c12cd84ae80a4f4c92551eb249667" - integrity sha512-a6+fJlHTiPjzUYnvwkcduJN0rAKWagQsQNoHJP/9mJ1CZjIkGysGtvVAjNpnrYWocj/Hbi36XmZ0H2aIKlol7A== + version "3.1.7" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz#72e3d5bd5d0ceb695e097a7f6f5ff6fcbf062b9a" + integrity sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ== dependencies: "@ethersproject/abi" "^5.1.2" "@ethersproject/address" "^5.0.2" - cbor "^5.0.2" + cbor "^8.1.0" chalk "^2.4.2" debug "^4.1.1" fs-extra "^7.0.1" lodash "^4.17.11" semver "^6.3.0" table "^6.8.0" - undici "^5.4.0" + undici "^5.14.0" "@nomiclabs/hardhat-waffle@^2.0.1": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.3.tgz#9c538a09c5ed89f68f5fd2dc3f78f16ed1d6e0b1" - integrity sha512-049PHSnI1CZq6+XTbrMbMv5NaL7cednTfPenx02k3cEh8wBMLa6ys++dBETJa6JjfwgA9nBhhHQ173LJv6k2Pg== - dependencies: - "@types/sinon-chai" "^3.2.3" - "@types/web3" "1.0.19" + version "2.0.6" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.6.tgz#d11cb063a5f61a77806053e54009c40ddee49a54" + integrity sha512-+Wz0hwmJGSI17B+BhU/qFRZ1l6/xMW82QGXE/Gi+WTmwgJrQefuBs1lIf7hzQ1hLk6hpkvb/zwcNkpVKRYTQYg== "@openzeppelin/contracts-upgradeable@4.5.2": version "4.5.2" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz#90d9e47bacfd8693bfad0ac8a394645575528d05" integrity sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA== -"@openzeppelin/contracts-upgradeable@^4.8.3": +"@openzeppelin/contracts-upgradeable@4.8.3": version "4.8.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.3.tgz#6b076a7b751811b90fe3a172a7faeaa603e13a3f" integrity sha512-SXDRl7HKpl2WDoJpn7CK/M9U4Z8gNXDHHChAKh0Iz+Wew3wu6CmFYBeie3je8V0GSXZAIYYwUktSrnW/kwVPtg== @@ -908,21 +711,22 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.5.0.tgz#3fd75d57de172b3743cdfc1206883f56430409cc" integrity sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA== -"@openzeppelin/contracts@^4.8.3": +"@openzeppelin/contracts@4.8.3": version "4.8.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.3.tgz#cbef3146bfc570849405f59cba18235da95a252a" integrity sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg== "@openzeppelin/upgrades-core@^1.24.1": - version "1.24.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.24.1.tgz#2b0c877f2a404d3384bacd4ce1e29bee14a14ea8" - integrity sha512-QhdIQDUykJ3vQauB6CheV7vk4zgn0e1iY+IDg7r1KqpA1m2bqIGjQCpzidW33K4bZc9zdJSPx2/Z6Um5KxCB7A== + version "1.27.1" + resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.27.1.tgz#4dff06915ec665ee45789471071ebc4354e834dd" + integrity sha512-6tLcu6jt0nYdJNr+LRicBgP3jp+//B+dixgB3KsvycSglCHNfmBNDf0ZQ3ZquDdLL0QQmKzIs1EBRVp6lNvPnQ== dependencies: cbor "^8.0.0" chalk "^4.1.0" compare-versions "^5.0.0" debug "^4.1.1" ethereumjs-util "^7.0.3" + minimist "^1.2.7" proper-lockfile "^4.1.1" solidity-ast "^0.4.15" @@ -968,21 +772,21 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== -"@scure/bip32@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.0.tgz#dea45875e7fbc720c2b4560325f1cf5d2246d95b" - integrity sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q== +"@scure/bip32@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.1.5.tgz#d2ccae16dcc2e75bc1d75f5ef3c66a338d1ba300" + integrity sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw== dependencies: - "@noble/hashes" "~1.1.1" - "@noble/secp256k1" "~1.6.0" + "@noble/hashes" "~1.2.0" + "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" -"@scure/bip39@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.0.tgz#92f11d095bae025f166bef3defcc5bf4945d419a" - integrity sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w== +"@scure/bip39@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" + integrity sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg== dependencies: - "@noble/hashes" "~1.1.1" + "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" "@sentry/core@5.30.0": @@ -1058,7 +862,7 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== -"@sindresorhus/is@^4.0.0": +"@sindresorhus/is@^4.0.0", "@sindresorhus/is@^4.6.0": version "4.6.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== @@ -1071,9 +875,9 @@ antlr4ts "^0.5.0-alpha.4" "@solidity-parser/parser@^0.14.0", "@solidity-parser/parser@^0.14.1", "@solidity-parser/parser@^0.14.3": - version "0.14.3" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.3.tgz#0d627427b35a40d8521aaa933cc3df7d07bfa36f" - integrity sha512-29g2SZ29HtsqA58pLCtopI1P/cPy5/UAzlcAXO6T/CNJimG6yA8kx4NaseMyJULiC+TEs02Y9/yeHzClqoA0hw== + version "0.14.5" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.5.tgz#87bc3cc7b068e08195c219c91cd8ddff5ef1a804" + integrity sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg== dependencies: antlr4ts "^0.5.0-alpha.4" @@ -1084,6 +888,13 @@ dependencies: antlr4ts "^0.5.0-alpha.4" +"@solidity-parser/parser@^0.16.0": + version "0.16.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.0.tgz#1fb418c816ca1fc3a1e94b08bcfe623ec4e1add4" + integrity sha512-ESipEcHyRHg4Np4SqBCfcXwyxxna1DgFVz69bgpLV8vzl/NP1DtcKsJ4dJZXWQhY/Z4J2LeKBiOkOVZn9ct33Q== + dependencies: + antlr4ts "^0.5.0-alpha.4" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -1098,27 +909,34 @@ dependencies: defer-to-connect "^2.0.0" +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== + dependencies: + defer-to-connect "^2.0.1" + "@truffle/error@^0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@truffle/error/-/error-0.1.1.tgz#e52026ac8ca7180d83443dca73c03e07ace2a301" integrity sha512-sE7c9IHIGdbK4YayH4BC8i8qMjoAOeg6nUXUDZZp8wlU21/EMpaG+CLx+KqcIPyR+GSWIW3Dm0PXkr2nlggFDA== -"@truffle/interface-adapter@^0.5.23": - version "0.5.23" - resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.23.tgz#a4103270e3c73746089b9e5807aaa1359f4725bb" - integrity sha512-nU8kChKgcUP+tELId1PMgHnmd2KcBdBer59TxfVqAZXRmt6blm2tpBbGYtKzTIdZlf6kMqVbZXdB6u1CJDqfxg== +"@truffle/interface-adapter@^0.5.25": + version "0.5.34" + resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.34.tgz#a45edc23d6ace0e01ebf237b668119f456729643" + integrity sha512-gPxabfMi2TueE4VxnNuyeudOfvGJQ1ofVC02PFw14cnRQhzH327JikjjQbZ1bT6S7kWl9H6P3hQPFeYFMHdm1g== dependencies: bn.js "^5.1.3" ethers "^4.0.32" - web3 "1.7.4" + web3 "1.10.0" "@truffle/provider@^0.2.24": - version "0.2.61" - resolved "https://registry.yarnpkg.com/@truffle/provider/-/provider-0.2.61.tgz#c20b891d77eca3c8907fa096f8f23bac7a180e8b" - integrity sha512-/aa4Xy+ag4zohfPWytA+u5QDDDvSdml6p/+zo5eN1nkmJ7hF6noxBlBHG+rEC3Pl+NNNQrbGZMzvlpfsOrNhMw== + version "0.2.64" + resolved "https://registry.yarnpkg.com/@truffle/provider/-/provider-0.2.64.tgz#7dd55117307fd019dcf81d08db5dc2bc5728f51c" + integrity sha512-ZwPsofw4EsCq/2h0t73SPnnFezu4YQWBmK4FxFaOUX0F+o8NsZuHKyfJzuZwyZbiktYmefM3yD9rM0Dj4BhNbw== dependencies: "@truffle/error" "^0.1.1" - "@truffle/interface-adapter" "^0.5.23" + "@truffle/interface-adapter" "^0.5.25" debug "^4.3.1" web3 "1.7.4" @@ -1138,9 +956,9 @@ integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== "@tsconfig/node16@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" - integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== "@typechain/ethers-v5@^2.0.0": version "2.0.0" @@ -1165,21 +983,9 @@ fs-extra "^9.1.0" "@types/abstract-leveldown@*": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#f055979a99f7654e84d6b8e6267419e9c4cfff87" - integrity sha512-q5veSX6zjUy/DlDhR4Y4cU0k2Ar+DT2LUraP00T19WLmTO6Se1djepCCaqU6nQrwcJ5Hyo/CWqxTzrrFg8eqbQ== - -"@types/async-eventemitter@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz#f8e6280e87e8c60b2b938624b0a3530fb3e24712" - integrity sha512-M2P4Ng26QbAeITiH7w1d7OxtldgfAe0wobpyJzVK/XOb0cUGKU2R4pfAhqcJBXAe2ife5ZOhSv4wk7p+ffURtg== - -"@types/bn.js@*", "@types/bn.js@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" - integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== - dependencies: - "@types/node" "*" + version "7.2.1" + resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.1.tgz#bb16403c17754b0c4d5772d71d03b924a03d4c80" + integrity sha512-YK8irIC+eMrrmtGx0H4ISn9GgzLd9dojZWJaMbjp1YHLl2VqqNFBNrL5Q3KjGf4VE3sf/4hmq6EhQZ7kZp1NoQ== "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": version "4.11.6" @@ -1188,20 +994,27 @@ dependencies: "@types/node" "*" -"@types/cacheable-request@^6.0.1": - version "6.0.2" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9" - integrity sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA== +"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" + integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== + dependencies: + "@types/node" "*" + +"@types/cacheable-request@^6.0.1", "@types/cacheable-request@^6.0.2": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== dependencies: "@types/http-cache-semantics" "*" - "@types/keyv" "*" + "@types/keyv" "^3.1.4" "@types/node" "*" - "@types/responselike" "*" + "@types/responselike" "^1.0.0" -"@types/chai@*", "@types/chai@^4.2.15": - version "4.3.3" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.3.tgz#3c90752792660c4b562ad73b3fbd68bf3bc7ae07" - integrity sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g== +"@types/chai@^4.2.15": + version "4.3.5" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.5.tgz#ae69bcbb1bebb68c4ac0b11e9d8ed04526b3562b" + integrity sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng== "@types/concat-stream@^1.6.0": version "1.6.1" @@ -1211,9 +1024,9 @@ "@types/node" "*" "@types/debug@^4.0.0": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" - integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + version "4.1.8" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.8.tgz#cef723a5d0a90990313faec2d1e22aee5eecb317" + integrity sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ== dependencies: "@types/ms" "*" @@ -1238,16 +1051,16 @@ integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== -"@types/keyv@*": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-4.2.0.tgz#65b97868ab757906f2dbb653590d7167ad023fa0" - integrity sha512-xoBtGl5R9jeKUhc8ZqeYaRDx04qqJ10yhhXYGmJ4Jr8qKpvMsDQQrNUvF/wUJ4klOtmJeJM+p2Xo3zp9uaC3tw== +"@types/keyv@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== dependencies: - keyv "*" + "@types/node" "*" "@types/level-errors@*": version "3.0.0" @@ -1291,17 +1104,17 @@ integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== "@types/node-fetch@^2.5.5": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" - integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + version "2.6.4" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.4.tgz#1bc3a26de814f6bf466b25aeb1473fa1afe6a660" + integrity sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg== dependencies: "@types/node" "*" form-data "^3.0.0" "@types/node@*": - version "18.11.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.2.tgz#c59b7641832531264fda3f1ba610362dc9a7dfc8" - integrity sha512-BWN3M23gLO2jVG8g/XHIRFWiiV4/GckeFIqbU/C4V3xpoBBWSMk4OZomouN0wCkfQFPqgZikyLr7DOYDysIkkw== + version "20.3.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.1.tgz#e8a83f1aa8b649377bb1fb5d7bac5cb90e784dfe" + integrity sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg== "@types/node@^10.0.3": version "10.17.60" @@ -1314,9 +1127,9 @@ integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== "@types/node@^14.14.28": - version "14.18.32" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.32.tgz#8074f7106731f1a12ba993fe8bad86ee73905014" - integrity sha512-Y6S38pFr04yb13qqHf8uk1nHE3lXgQ30WZbv1mLliV9pt0NjvqdWttLcrOYLnXbOafknVYRHZGoMSpR9UwfYow== + version "14.18.51" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.51.tgz#cb90935b89c641201c3d07a595c3e22d1cfaa417" + integrity sha512-P9bsdGFPpVtofEKlhWMVS2qqx1A/rt9QBfihWlklfHHpUpjtYse5AzFz6j4DWrARLYh6gRnw9+5+DJcrq3KvBA== "@types/node@^8.0.0": version "8.10.66" @@ -1331,16 +1144,17 @@ "@types/node" "*" "@types/prettier@^2.1.1": - version "2.7.1" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e" - integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow== + version "2.7.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f" + integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA== "@types/prompts@^2.0.14": - version "2.4.1" - resolved "https://registry.yarnpkg.com/@types/prompts/-/prompts-2.4.1.tgz#d47adcb608a0afcd48121ff7c75244694a3a04c5" - integrity sha512-1Mqzhzi9W5KlooNE4o0JwSXGUDeQXKldbGn9NO4tpxwZbHXYd+WcKpCksG2lbhH7U9I9LigfsdVsP2QAY0lNPA== + version "2.4.4" + resolved "https://registry.yarnpkg.com/@types/prompts/-/prompts-2.4.4.tgz#dd5a1d41cb1bcd0fc4464bf44a0c8354f36ea735" + integrity sha512-p5N9uoTH76lLvSAaYSZtBCdEXzpOOufsRjnhjVSrZGXikVGHX9+cc9ERtHRV4hvBKHyZb1bg4K+56Bd2TqUn4A== dependencies: "@types/node" "*" + kleur "^3.0.3" "@types/qs@^6.2.31", "@types/qs@^6.9.7": version "6.9.7" @@ -1354,7 +1168,7 @@ dependencies: "@types/node" "*" -"@types/responselike@*", "@types/responselike@^1.0.0": +"@types/responselike@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== @@ -1369,42 +1183,9 @@ "@types/node" "*" "@types/semver@^7.3.12": - version "7.3.12" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.12.tgz#920447fdd78d76b19de0438b7f60df3c4a80bf1c" - integrity sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A== - -"@types/sinon-chai@^3.2.3": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.8.tgz#5871d09ab50d671d8e6dd72e9073f8e738ac61dc" - integrity sha512-d4ImIQbT/rKMG8+AXpmcan5T2/PNeSjrYhvkwet6z0p8kzYtfgA32xzOBlbU0yqJfq+/0Ml805iFoODO0LP5/g== - dependencies: - "@types/chai" "*" - "@types/sinon" "*" - -"@types/sinon@*": - version "10.0.13" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.13.tgz#60a7a87a70d9372d0b7b38cc03e825f46981fb83" - integrity sha512-UVjDqJblVNQYvVNUsj0PuYYw0ELRmgt1Nt5Vk0pT5f16ROGfcKJY8o1HVuMOJOpD727RrGB9EGvoaTQE5tgxZQ== - dependencies: - "@types/sinonjs__fake-timers" "*" - -"@types/sinonjs__fake-timers@*": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" - integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== - -"@types/underscore@*": - version "1.11.4" - resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.4.tgz#62e393f8bc4bd8a06154d110c7d042a93751def3" - integrity sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg== - -"@types/web3@1.0.19": - version "1.0.19" - resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" - integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== - dependencies: - "@types/bn.js" "*" - "@types/underscore" "*" + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== "@types/yauzl@^2.9.1": version "2.10.0" @@ -1414,12 +1195,11 @@ "@types/node" "*" "@typescript-eslint/eslint-plugin-tslint@^5.30.6": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin-tslint/-/eslint-plugin-tslint-5.40.1.tgz#5cfdf20110a21092c401b7997812907b37bb7fac" - integrity sha512-OrcFPu0E7QdjxkUgCX8+lYZJWq2xLMDPXM4B3MlJxGYYbSmJhGszL7Yp4cdQyX3wn+Kv9JwPxUnjzAu8u6fX6Q== + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin-tslint/-/eslint-plugin-tslint-5.60.0.tgz#9d3b6cc8f9770e714683e441d580d3c109112d6f" + integrity sha512-4QoOx2ixrFpst/HcvCITjrYOmoDtGm/MYHtCh9zCNDVnaRaJGTs9sOUQmRyNea+wAfDNpRFgu05Nn4HxfAvxbw== dependencies: - "@typescript-eslint/utils" "5.40.1" - lodash "^4.17.21" + "@typescript-eslint/utils" "5.60.0" "@typescript-eslint/eslint-plugin@^4.29.0": version "4.33.0" @@ -1465,23 +1245,23 @@ "@typescript-eslint/types" "4.33.0" "@typescript-eslint/visitor-keys" "4.33.0" -"@typescript-eslint/scope-manager@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.40.1.tgz#a7a5197dfd234622a2421ea590ee0ccc02e18dfe" - integrity sha512-jkn4xsJiUQucI16OLCXrLRXDZ3afKhOIqXs4R3O+M00hdQLKR58WuyXPZZjhKLFCEP2g+TXdBRtLQ33UfAdRUg== +"@typescript-eslint/scope-manager@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.60.0.tgz#ae511967b4bd84f1d5e179bb2c82857334941c1c" + integrity sha512-hakuzcxPwXi2ihf9WQu1BbRj1e/Pd8ZZwVTG9kfbxAMZstKz8/9OoexIwnmLzShtsdap5U/CoQGRCWlSuPbYxQ== dependencies: - "@typescript-eslint/types" "5.40.1" - "@typescript-eslint/visitor-keys" "5.40.1" + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/visitor-keys" "5.60.0" "@typescript-eslint/types@4.33.0": version "4.33.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== -"@typescript-eslint/types@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.40.1.tgz#de37f4f64de731ee454bb2085d71030aa832f749" - integrity sha512-Icg9kiuVJSwdzSQvtdGspOlWNjVDnF3qVIKXdJ103o36yRprdl3Ge5cABQx+csx960nuMF21v8qvO31v9t3OHw== +"@typescript-eslint/types@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.60.0.tgz#3179962b28b4790de70e2344465ec97582ce2558" + integrity sha512-ascOuoCpNZBccFVNJRSC6rPq4EmJ2NkuoKnd6LDNyAQmdDnziAtxbCGWCbefG1CNzmDvd05zO36AmB7H8RzKPA== "@typescript-eslint/typescript-estree@4.33.0": version "4.33.0" @@ -1496,31 +1276,31 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.40.1.tgz#9a7d25492f02c69882ce5e0cd1857b0c55645d72" - integrity sha512-5QTP/nW5+60jBcEPfXy/EZL01qrl9GZtbgDZtDPlfW5zj/zjNrdI2B5zMUHmOsfvOr2cWqwVdWjobCiHcedmQA== +"@typescript-eslint/typescript-estree@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.0.tgz#4ddf1a81d32a850de66642d9b3ad1e3254fb1600" + integrity sha512-R43thAuwarC99SnvrBmh26tc7F6sPa2B3evkXp/8q954kYL6Ro56AwASYWtEEi+4j09GbiNAHqYwNNZuNlARGQ== dependencies: - "@typescript-eslint/types" "5.40.1" - "@typescript-eslint/visitor-keys" "5.40.1" + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/visitor-keys" "5.60.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.40.1.tgz#3204fb73a559d3b7bab7dc9d3c44487c2734a9ca" - integrity sha512-a2TAVScoX9fjryNrW6BZRnreDUszxqm9eQ9Esv8n5nXApMW0zeANUYlwh/DED04SC/ifuBvXgZpIK5xeJHQ3aw== +"@typescript-eslint/utils@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.60.0.tgz#4667c5aece82f9d4f24a667602f0f300864b554c" + integrity sha512-ba51uMqDtfLQ5+xHtwlO84vkdjrqNzOnqrnwbMHMRY8Tqeme8C2Q8Fc7LajfGR+e3/4LoYiWXUM6BpIIbHJ4hQ== dependencies: + "@eslint-community/eslint-utils" "^4.2.0" "@types/json-schema" "^7.0.9" "@types/semver" "^7.3.12" - "@typescript-eslint/scope-manager" "5.40.1" - "@typescript-eslint/types" "5.40.1" - "@typescript-eslint/typescript-estree" "5.40.1" + "@typescript-eslint/scope-manager" "5.60.0" + "@typescript-eslint/types" "5.60.0" + "@typescript-eslint/typescript-estree" "5.60.0" eslint-scope "^5.1.1" - eslint-utils "^3.0.0" semver "^7.3.7" "@typescript-eslint/visitor-keys@4.33.0": @@ -1531,12 +1311,12 @@ "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" -"@typescript-eslint/visitor-keys@5.40.1": - version "5.40.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.40.1.tgz#f3d2bf5af192f4432b84cec6fdcb387193518754" - integrity sha512-A2DGmeZ+FMja0geX5rww+DpvILpwo1OsiQs0M+joPWJYsiEFBLsH0y1oFymPNul6Z5okSmHpP4ivkc2N0Cgfkw== +"@typescript-eslint/visitor-keys@5.60.0": + version "5.60.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.0.tgz#b48b29da3f5f31dd1656281727004589d2722a66" + integrity sha512-wm9Uz71SbCyhUKgcaPRauBdTegUyY/ZWl8gLwD/i/ybJqscrrdVSFImpvUz16BLPChIeKBK5Fa9s6KDQjsjyWw== dependencies: - "@typescript-eslint/types" "5.40.1" + "@typescript-eslint/types" "5.60.0" eslint-visitor-keys "^3.3.0" "@ungap/promise-all-settled@1.1.2": @@ -1566,18 +1346,10 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.3.tgz#78a67d3d84da55ee15201486ab44c09560070741" - integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== - dependencies: - buffer "^6.0.3" - catering "^2.1.0" - is-buffer "^2.0.5" - level-supports "^4.0.0" - level-transcoder "^1.0.1" - module-error "^1.0.1" - queue-microtask "^1.2.3" +abortcontroller-polyfill@^1.7.3: + version "1.7.5" + resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" + integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== abstract-leveldown@3.0.0: version "3.0.0" @@ -1637,7 +1409,7 @@ accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-jsx@^5.0.0, acorn-jsx@^5.3.1: +acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== @@ -1647,25 +1419,20 @@ acorn-walk@^8.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^6.0.7: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.4.1: - version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" - integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== + version "8.9.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" + integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== address@^1.0.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/address/-/address-1.2.1.tgz#25bb61095b7522d65b357baa11bc05492d4c8acd" - integrity sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA== + version "1.2.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" + integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== adm-zip@^0.4.16: version "0.4.16" @@ -1697,7 +1464,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: +ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -1708,9 +1475,9 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.6.1, ajv@^6.9.1: uri-js "^4.2.2" ajv@^8.0.1: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" - integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -1737,11 +1504,6 @@ ansi-colors@^4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -1788,10 +1550,10 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -antlr4@4.7.1: - version "4.7.1" - resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" - integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== +antlr4@^4.11.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.13.0.tgz#25c0b17f0d9216de114303d38bafd6f181d5447f" + integrity sha512-zooUbt+UscjnWyOrsuY/tVFL4rwrAGwOivpQmvmUDE22hy/lUA467Rc1rcixyRwcRUIXFYBwv7+dClDSHdmmew== antlr4ts@^0.5.0-alpha.4: version "0.5.0-alpha.4" @@ -1799,9 +1561,9 @@ antlr4ts@^0.5.0-alpha.4: integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== anymatch@~3.1.1, anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -1859,6 +1621,14 @@ array-back@^2.0.0: dependencies: typical "^2.6.1" +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -1879,14 +1649,14 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== -array.prototype.reduce@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz#8167e80089f78bff70a99e20bd4201d4663b0a6f" - integrity sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw== +array.prototype.reduce@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" + integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" @@ -1927,16 +1697,11 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== -ast-parents@0.0.1: +ast-parents@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" integrity sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA== -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -1999,9 +1764,9 @@ aws-sign2@~0.7.0: integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== axios-debug-log@^1.0.0: version "1.0.0" @@ -2018,10 +1783,18 @@ axios@^0.21.1: dependencies: follow-redirects "^1.14.0" +axios@^0.27.2: + version "0.27.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + axios@^1.3.4: - version "1.3.6" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.6.tgz#1ace9a9fb994314b5f6327960918406fa92c6646" - integrity sha512-PEcdkk7JcdPiMDkvM4K6ZBRYq9keuVJsToxm2zQIM70Qqo2WHTdJZMXcG9X+RmRp2VPNUQC8W1RAGbgt6b1yMg== + version "1.4.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f" + integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" @@ -2595,22 +2368,10 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== -bigint-crypto-utils@^3.0.23: - version "3.1.7" - resolved "https://registry.yarnpkg.com/bigint-crypto-utils/-/bigint-crypto-utils-3.1.7.tgz#c4c1b537c7c1ab7aadfaecf3edfd45416bf2c651" - integrity sha512-zpCQpIE2Oy5WIQpjC9iYZf8Uh9QqoS51ZCooAcNvzv1AQ3VWdT52D0ksr1+/faeK8HVIej1bxXcP75YcqH3KPA== - dependencies: - bigint-mod-arith "^3.1.0" - -bigint-mod-arith@^3.1.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bigint-mod-arith/-/bigint-mod-arith-3.1.2.tgz#658e416bc593a463d97b59766226d0a3021a76b1" - integrity sha512-nx8J8bBeiRR+NlsROFH9jHswW5HO8mgfOSqW0AmjicMMvaONDa8AO+5ViKDUUNytBPWiwfvZP4/Bj4Y3lUfvgQ== - -bignumber.js@^9.0.0, bignumber.js@^9.0.1: - version "9.1.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.0.tgz#8d340146107fe3a6cb8d40699643c302e8773b62" - integrity sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A== +bignumber.js@^9.0.0: + version "9.1.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" + integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== binary-extensions@^2.0.0: version "2.2.0" @@ -2662,7 +2423,7 @@ bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.1.3, bn.js@^5.2.0, bn.js@^5.2 resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -body-parser@1.20.1, body-parser@^1.16.0: +body-parser@1.20.1: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== @@ -2680,6 +2441,24 @@ body-parser@1.20.1, body-parser@^1.16.0: type-is "~1.6.18" unpipe "1.0.0" +body-parser@^1.16.0: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -2728,16 +2507,6 @@ brorand@^1.0.1, brorand@^1.1.0: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browser-level@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browser-level/-/browser-level-1.0.1.tgz#36e8c3183d0fe1c405239792faaab5f315871011" - integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.1" - module-error "^1.0.2" - run-parallel-limit "^1.1.0" - browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" @@ -2856,14 +2625,6 @@ buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: base64-js "^1.3.1" ieee754 "^1.1.13" -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - bufferutil@^4.0.1: version "4.0.7" resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" @@ -2923,6 +2684,11 @@ cacheable-lookup@^5.0.3: resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== +cacheable-lookup@^6.0.4: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz#0330a543471c61faa4e9035db583aad753b36385" + integrity sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww== + cacheable-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" @@ -2937,9 +2703,9 @@ cacheable-request@^6.0.0: responselike "^1.0.2" cacheable-request@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" - integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== + version "7.0.4" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" + integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== dependencies: clone-response "^1.0.2" get-stream "^5.1.0" @@ -2965,25 +2731,6 @@ call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== - callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -3005,29 +2752,16 @@ camelcase@^6.0.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30000844: - version "1.0.30001422" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001422.tgz#f2d7c6202c49a8359e6e35add894d88ef93edba1" - integrity sha512-hSesn02u1QacQHhaxl/kNMZwqVG35Sz/8DgvmgedxSH8z9UUpcDYSPYgsj3x5dQNRcNp6BwpSfQfVzYUTm+fog== + version "1.0.30001508" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001508.tgz#4461bbc895c692a96da399639cc1e146e7302a33" + integrity sha512-sdQZOJdmt3GJs1UMNpCCCyeuS2IEGLXnHyAo9yIO5JJDjbjoVRij4M1qep6P6gFpptD1PqIYgzM+gwJbOi92mw== caseless@^0.12.0, caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -catering@^2.1.0, catering@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" - integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== - -cbor@^5.0.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c" - integrity sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A== - dependencies: - bignumber.js "^9.0.1" - nofilter "^1.0.4" - -cbor@^8.0.0: +cbor@^8.0.0, cbor@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== @@ -3035,13 +2769,13 @@ cbor@^8.0.0: nofilter "^3.1.0" chai@^4.2.0: - version "4.3.6" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" - integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" - deep-eql "^3.0.1" + deep-eql "^4.1.2" get-func-name "^2.0.0" loupe "^2.3.1" pathval "^1.1.1" @@ -3058,7 +2792,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3075,11 +2809,6 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - "charenc@>= 0.0.1": version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" @@ -3196,17 +2925,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classic-level@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/classic-level/-/classic-level-1.2.0.tgz#2d52bdec8e7a27f534e67fdeb890abef3e643c27" - integrity sha512-qw5B31ANxSluWz9xBzklRWTUAJ1SXIdaVKTVS7HcTGKOAmExx65Wo5BUICW+YGORe2FOUaDghoI9ZDxj82QcFg== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.0" - module-error "^1.0.1" - napi-macros "~2.0.0" - node-gyp-build "^4.3.0" - clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -3223,13 +2941,6 @@ cli-color@^2.0.3: memoizee "^0.4.15" timers-ext "^0.1.7" -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== - dependencies: - restore-cursor "^2.0.0" - cli-table3@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" @@ -3240,11 +2951,6 @@ cli-table3@^0.5.0: optionalDependencies: colors "^1.1.2" -cli-width@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" - integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== - cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -3347,11 +3053,6 @@ command-line-args@^4.0.7: find-replace "^1.0.3" typical "^2.6.1" -commander@2.18.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" - integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== - commander@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" @@ -3367,15 +3068,15 @@ commander@^2.12.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^9.2.0: +commander@^9.2.0, commander@^9.4.0: version "9.5.0" resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== compare-versions@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-5.0.1.tgz#14c6008436d994c3787aba38d4087fabe858555e" - integrity sha512-v8Au3l0b+Nwkp4G142JcgJFh1/TUhdxut7wzD1Nq1dyp5oa3tXaqb03EXOAB6jS4gMlalkjAUPZBMiAfKUixHQ== + version "5.0.3" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-5.0.3.tgz#a9b34fea217472650ef4a2651d905f42c28ebfd7" + integrity sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A== component-emitter@^1.2.1: version "1.3.0" @@ -3413,10 +3114,10 @@ content-hash@^2.5.2: multicodec "^0.5.5" multihashes "^0.4.15" -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== convert-source-map@^1.5.1: version "1.9.0" @@ -3463,9 +3164,9 @@ cookie@^0.4.1: integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== cookiejar@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" - integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== + version "2.1.4" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" + integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== copy-descriptor@^0.1.0: version "0.1.1" @@ -3473,9 +3174,9 @@ copy-descriptor@^0.1.0: integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== core-js-pure@^3.0.1: - version "3.25.5" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.5.tgz#79716ba54240c6aa9ceba6eee08cf79471ba184d" - integrity sha512-oml3M22pHM+igfWHDfdLVq2ShWmjM2V4L+dQEBs0DWVIqEm9WHCwGAlZ6BmyBQGy5sFrJmcx+856D9lVKyGWYg== + version "3.31.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.31.0.tgz#052fd9e82fbaaf86457f5db1fadcd06f15966ff2" + integrity sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg== core-js@^2.4.0, core-js@^2.5.0: version "2.6.12" @@ -3500,15 +3201,15 @@ cors@^2.8.1: object-assign "^4" vary "^1" -cosmiconfig@^5.0.7: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== +cosmiconfig@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.2.0.tgz#f7d17c56a590856cd1e7cee98734dca272b0d8fd" + integrity sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ== dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" crc-32@^1.2.0: version "1.2.2" @@ -3566,6 +3267,13 @@ cross-fetch@^2.1.0, cross-fetch@^2.1.1: node-fetch "^2.6.7" whatwg-fetch "^2.0.4" +cross-fetch@^3.1.4: + version "3.1.6" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.6.tgz#bae05aa31a4da760969756318feeee6e70f15d6c" + integrity sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g== + dependencies: + node-fetch "^2.6.11" + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -3690,9 +3398,9 @@ decamelize@^4.0.0: integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== decompress-response@^3.3.0: version "3.3.0" @@ -3708,10 +3416,10 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== dependencies: type-detect "^4.0.0" @@ -3737,7 +3445,7 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== -defer-to-connect@^2.0.0: +defer-to-connect@^2.0.0, defer-to-connect@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== @@ -3765,10 +3473,10 @@ deferred-leveldown@~5.3.0: abstract-leveldown "~6.2.1" inherits "^2.0.3" -define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== +define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== dependencies: has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -3795,7 +3503,7 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -defined@~1.0.0: +defined@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== @@ -3811,9 +3519,9 @@ depd@2.0.0: integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + version "1.1.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" + integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== dependencies: inherits "^2.0.1" minimalistic-assert "^1.0.0" @@ -3905,7 +3613,7 @@ domelementtype@^2.3.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== -domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: +domhandler@^5.0.2, domhandler@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== @@ -3913,13 +3621,13 @@ domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: domelementtype "^2.3.0" domutils@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" - integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== dependencies: dom-serializer "^2.0.0" domelementtype "^2.3.0" - domhandler "^5.0.1" + domhandler "^5.0.3" dotenv@^10.0.0: version "10.0.0" @@ -3952,9 +3660,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.3.47: - version "1.4.284" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" - integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== + version "1.4.440" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.440.tgz#d3b1eeb36b717eb479a240c0406ac1fa67901762" + integrity sha512-r6dCgNpRhPwiWlxbHzZQ/d9swfPaEJGi8ekqRBwQYaR3WmA5VkqQfBWSDDjuJU1ntO+W9tHx8OHV/96Q8e0dVw== elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" @@ -3969,11 +3677,6 @@ elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5 minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -emoji-regex@^10.1.0: - version "10.2.1" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.2.1.tgz#a41c330d957191efd3d9dfe6e1e8e1e9ab048b3f" - integrity sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA== - emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -4060,41 +3763,60 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.19.0, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.0, es-abstract@^1.20.1: - version "1.20.4" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.4.tgz#1d103f9f8d78d4cf0713edcd6d0ed1a46eed5861" - integrity sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA== +es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" es-to-primitive "^1.2.1" - function-bind "^1.1.1" function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" + get-intrinsic "^1.2.0" get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" has "^1.0.3" has-property-descriptors "^1.0.0" + has-proto "^1.0.1" has-symbols "^1.0.3" - internal-slot "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" is-callable "^1.2.7" is-negative-zero "^2.0.2" is-regex "^1.1.4" is-shared-array-buffer "^1.0.2" is-string "^1.0.7" + is-typed-array "^1.1.10" is-weakref "^1.0.2" - object-inspect "^1.12.2" + object-inspect "^1.12.3" object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.4.3" safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" es-array-method-boxes-properly@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -4122,6 +3844,11 @@ es6-iterator@^2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" +es6-promise@^4.2.8: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + es6-symbol@^3.1.1, es6-symbol@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" @@ -4173,9 +3900,9 @@ escodegen@1.8.x: source-map "~0.2.0" eslint-config-prettier@^8.3.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" - integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== + version "8.8.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" + integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== eslint-plugin-mocha@^9.0.0: version "9.0.0" @@ -4192,28 +3919,13 @@ eslint-plugin-prettier@^4.0.0: dependencies: prettier-linter-helpers "^1.0.0" -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-utils@^1.3.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" + estraverse "^4.1.1" eslint-utils@^2.1.0: version "2.1.0" @@ -4229,7 +3941,7 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== @@ -4240,51 +3952,9 @@ eslint-visitor-keys@^2.0.0: integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== eslint-visitor-keys@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" - integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== - -eslint@^5.6.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" - table "^5.2.3" - text-table "^0.2.0" + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== eslint@^7.32.0: version "7.32.0" @@ -4332,15 +4002,6 @@ eslint@^7.32.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== - dependencies: - acorn "^6.0.7" - acorn-jsx "^5.0.0" - eslint-visitor-keys "^1.0.0" - espree@^7.3.0, espree@^7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" @@ -4360,14 +4021,14 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1, esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== +esquery@^1.4.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== dependencies: estraverse "^5.1.0" -esrecurse@^4.1.0, esrecurse@^4.3.0: +esrecurse@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== @@ -4562,7 +4223,7 @@ ethereum-common@^0.0.18: resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" integrity sha512-EoltVQTRNg2Uy4o84qpa2aXymXDJhxm7eos/ACOg0DG4baAbMjhbdAEsx9GeE8sC3XCxnYvrrzZDH8D8MtA2iQ== -ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.2, ethereum-cryptography@^0.1.3: +ethereum-cryptography@^0.1.2, ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== @@ -4584,14 +4245,14 @@ ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.2, ethereum-cryptography setimmediate "^1.0.5" ethereum-cryptography@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz#74f2ac0f0f5fe79f012c889b3b8446a9a6264e6d" - integrity sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ== + version "1.2.0" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz#5ccfa183e85fdaf9f9b299a79430c044268c9b3a" + integrity sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw== dependencies: - "@noble/hashes" "1.1.2" - "@noble/secp256k1" "1.6.3" - "@scure/bip32" "1.1.0" - "@scure/bip39" "1.1.0" + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@scure/bip32" "1.1.5" + "@scure/bip39" "1.1.1" ethereum-waffle@^3.2.0: version "3.4.4" @@ -4746,7 +4407,7 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum rlp "^2.0.0" safe-buffer "^5.1.1" -ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5: +ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== @@ -4825,43 +4486,7 @@ ethers@^4.0.32, ethers@^4.0.40: uuid "2.0.1" xmlhttprequest "1.8.0" -ethers@^5.0.1, ethers@^5.0.2, ethers@^5.4.5, ethers@^5.5.2: - version "5.7.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.1.tgz#48c83a44900b5f006eb2f65d3ba6277047fd4f33" - integrity sha512-5krze4dRLITX7FpU8J4WscXqADiKmyeNlylmmDLbS95DaZpBhDe2YSwRQwKXWNyXcox7a3gBgm/MkGXV1O1S/Q== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.1" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - -ethers@^5.7.2: +ethers@^5.0.1, ethers@^5.0.2, ethers@^5.1.0, ethers@^5.4.5, ethers@^5.5.2, ethers@^5.6.9, ethers@^5.7.2: version "5.7.2" resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -5034,15 +4659,6 @@ extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -5090,10 +4706,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== +fast-diff@^1.1.2, fast-diff@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== fast-glob@^3.0.3, fast-glob@^3.2.9: version "3.2.12" @@ -5117,9 +4733,9 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== dependencies: reusify "^1.0.4" @@ -5137,20 +4753,6 @@ fetch-ponyfill@^4.0.0: dependencies: node-fetch "~1.7.1" -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -5254,15 +4856,6 @@ find-yarn-workspace-root@^2.0.0: dependencies: micromatch "^4.0.2" -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -5283,11 +4876,6 @@ flat@^5.0.2: resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - flatted@^3.1.0: version "3.2.7" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" @@ -5305,7 +4893,7 @@ fmix@^0.1.0: dependencies: imul "^1.0.0" -follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.15.0: +follow-redirects@^1.12.1, follow-redirects@^1.14.0, follow-redirects@^1.14.9, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -5327,6 +4915,11 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== +form-data-encoder@1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.1.tgz#ac80660e4f87ee0d3d3c3638b7da8278ddb8ec96" + integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg== + form-data@^2.2.0: version "2.5.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" @@ -5442,7 +5035,7 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.1.0: +fs-extra@^9.0.0, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -5499,7 +5092,7 @@ functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== -functions-have-names@^1.2.2: +functions-have-names@^1.2.2, functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== @@ -5565,13 +5158,14 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== dependencies: function-bind "^1.1.1" has "^1.0.3" + has-proto "^1.0.1" has-symbols "^1.0.3" get-port@^3.1.0: @@ -5598,6 +5192,11 @@ get-stream@^5.1.0: dependencies: pump "^3.0.0" +get-stream@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -5680,7 +5279,7 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6, glob@~7.2.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.1: +glob@^8.0.1, glob@^8.0.3: version "8.1.0" resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== @@ -5715,15 +5314,10 @@ global@~4.4.0: min-document "^2.19.0" process "^0.11.10" -globals@^11.7.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^13.6.0, globals@^13.9.0: - version "13.17.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" - integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== dependencies: type-fest "^0.20.2" @@ -5732,6 +5326,13 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + globby@^10.0.1: version "10.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" @@ -5758,6 +5359,32 @@ globby@^11.0.3, globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +got@12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-12.1.0.tgz#099f3815305c682be4fd6b0ee0726d8e4c6b0af4" + integrity sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig== + dependencies: + "@sindresorhus/is" "^4.6.0" + "@szmarczak/http-timer" "^5.0.1" + "@types/cacheable-request" "^6.0.2" + "@types/responselike" "^1.0.0" + cacheable-lookup "^6.0.4" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + form-data-encoder "1.7.1" + get-stream "^6.0.1" + http2-wrapper "^2.1.10" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^2.0.0" + got@9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -5776,9 +5403,9 @@ got@9.6.0: url-parse-lax "^3.0.0" got@^11.8.5: - version "11.8.5" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.5.tgz#ce77d045136de56e8f024bebb82ea349bc730046" - integrity sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ== + version "11.8.6" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" + integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== dependencies: "@sindresorhus/is" "^4.0.0" "@szmarczak/http-timer" "^4.0.5" @@ -5793,9 +5420,9 @@ got@^11.8.5: responselike "^2.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== growl@1.10.5: version "1.10.5" @@ -5918,62 +5545,6 @@ hardhat@2.9.9: uuid "^8.3.2" ws "^7.4.6" -hardhat@^2.6.6: - version "2.12.0" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.0.tgz#51e59f1ff4991bcb66d1a380ea807e6c15fcac34" - integrity sha512-mNJFbVG479HwOzxiaLxobyvED2M1aEAuPPYhEo1+88yicMDSTrU2JIS7vV+V0GSNQKaDoiHCmV6bcKjiljT/dQ== - dependencies: - "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "^4.0.0" - "@nomicfoundation/ethereumjs-blockchain" "^6.0.0" - "@nomicfoundation/ethereumjs-common" "^3.0.0" - "@nomicfoundation/ethereumjs-evm" "^1.0.0" - "@nomicfoundation/ethereumjs-rlp" "^4.0.0" - "@nomicfoundation/ethereumjs-statemanager" "^1.0.0" - "@nomicfoundation/ethereumjs-trie" "^5.0.0" - "@nomicfoundation/ethereumjs-tx" "^4.0.0" - "@nomicfoundation/ethereumjs-util" "^8.0.0" - "@nomicfoundation/ethereumjs-vm" "^6.0.0" - "@nomicfoundation/solidity-analyzer" "^0.1.0" - "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" - abort-controller "^3.0.0" - adm-zip "^0.4.16" - aggregate-error "^3.0.0" - ansi-escapes "^4.3.0" - chalk "^2.4.2" - chokidar "^3.4.0" - ci-info "^2.0.0" - debug "^4.1.1" - enquirer "^2.3.0" - env-paths "^2.2.0" - ethereum-cryptography "^1.0.3" - ethereumjs-abi "^0.6.8" - find-up "^2.1.0" - fp-ts "1.19.3" - fs-extra "^7.0.1" - glob "7.2.0" - immutable "^4.0.0-rc.12" - io-ts "1.10.4" - keccak "^3.0.2" - lodash "^4.17.11" - mnemonist "^0.38.0" - mocha "^10.0.0" - p-map "^4.0.0" - qs "^6.7.0" - raw-body "^2.4.1" - resolve "1.17.0" - semver "^6.3.0" - solc "0.7.3" - source-map-support "^0.5.13" - stacktrace-parser "^0.1.10" - tsort "0.0.1" - undici "^5.4.0" - uuid "^8.3.2" - ws "^7.4.6" - has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -6008,7 +5579,12 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" -has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.0, has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -6136,9 +5712,9 @@ http-basic@^8.1.1: parse-cache-control "^1.0.1" http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== http-errors@2.0.0: version "2.0.0" @@ -6180,6 +5756,14 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" +http2-wrapper@^2.1.10: + version "2.2.0" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.0.tgz#b80ad199d216b7d3680195077bd7b9060fa9d7f3" + integrity sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" + https-proxy-agent@5.0.1, https-proxy-agent@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -6188,7 +5772,7 @@ https-proxy-agent@5.0.1, https-proxy-agent@^5.0.0: agent-base "6" debug "4" -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -6209,7 +5793,7 @@ idna-uts46-hx@^2.3.1: dependencies: punycode "2.1.0" -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.1.13: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -6219,10 +5803,10 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.1.8, ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +ignore@^5.1.1, ignore@^5.1.8, ignore@^5.2.0, ignore@^5.2.4: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== immediate@^3.2.3: version "3.3.0" @@ -6235,17 +5819,9 @@ immediate@~3.2.3: integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== immutable@^4.0.0-rc.12: - version "4.1.0" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef" - integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ== - -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" + version "4.3.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.0.tgz#eb1738f14ffb39fd068b1dbe1296117484dd34be" + integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" @@ -6288,31 +5864,12 @@ ini@^1.3.5: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -inquirer@^6.2.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" - integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== dependencies: - get-intrinsic "^1.1.0" + get-intrinsic "^1.2.0" has "^1.0.3" side-channel "^1.0.4" @@ -6372,6 +5929,15 @@ is-arguments@^1.0.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -6404,7 +5970,7 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@^2.0.5, is-buffer@~2.0.3: +is-buffer@~2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== @@ -6421,10 +5987,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== dependencies: has "^1.0.3" @@ -6467,11 +6033,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== - is-docker@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" @@ -6620,15 +6181,15 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.3, is-typed-array@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.9.tgz#246d77d2871e7d9f5aeb1d54b9f52c71329ece67" - integrity sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A== +is-typed-array@^1.1.10, is-typed-array@^1.1.3, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== dependencies: available-typed-arrays "^1.0.5" call-bind "^1.0.2" - es-abstract "^1.20.0" for-each "^0.3.3" + gopd "^1.0.1" has-tostringtag "^1.0.0" is-typedarray@^1.0.0, is-typedarray@~1.0.0: @@ -6680,6 +6241,11 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -6735,7 +6301,7 @@ js-yaml@3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: +js-yaml@3.x, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -6743,7 +6309,7 @@ js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@4.1.0: +js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -6775,10 +6341,10 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: version "3.8.0" @@ -6825,11 +6391,11 @@ json-stable-stringify-without-jsonify@^1.0.1: integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha512-i/J297TW6xyj7sDFa7AmBPkQvLIxWr2kKPWI26tXydnZrzVAocNqn5DMNT1Mzk0vit1V5UkRM7C1KdVNp7Lmcg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz#e06f23128e0bbe342dc996ed5a19e28b57b580e0" + integrity sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g== dependencies: - jsonify "~0.0.0" + jsonify "^0.0.1" json-stringify-safe@~5.0.1: version "5.0.1" @@ -6864,7 +6430,7 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jsonify@~0.0.0: +jsonify@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== @@ -6892,22 +6458,15 @@ keccak@3.0.1: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" -keccak@^3.0.0, keccak@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" - integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== +keccak@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.3.tgz#4bc35ad917be1ef54ff246f904c2bbbf9ac61276" + integrity sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ== dependencies: node-addon-api "^2.0.0" node-gyp-build "^4.2.0" readable-stream "^3.6.0" -keyv@*, keyv@^4.0.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.0.tgz#dbce9ade79610b6e641a9a65f2f6499ba06b9bc6" - integrity sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA== - dependencies: - json-buffer "3.0.1" - keyv@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" @@ -6915,6 +6474,13 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" +keyv@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" + integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== + dependencies: + json-buffer "3.0.1" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -6953,7 +6519,7 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" -klaw@^4.1.0: +klaw@^4.0.1, klaw@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/klaw/-/klaw-4.1.0.tgz#5df608067d8cb62bbfb24374f8e5d956323338f3" integrity sha512-1zGZ9MF9H22UnkpVeuaGKOjfA2t6WrfdrJmGjy16ykcjnKQDmHVX+KI477rpbGevz/5FD4MC3xf1oxylBgcaQw== @@ -7107,11 +6673,6 @@ level-sublevel@6.6.4: typewiselite "~1.0.0" xtend "~4.0.0" -level-supports@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" - integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== - level-supports@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d" @@ -7119,14 +6680,6 @@ level-supports@~1.0.0: dependencies: xtend "^4.0.2" -level-transcoder@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/level-transcoder/-/level-transcoder-1.0.1.tgz#f8cef5990c4f1283d4c86d949e73631b0bc8ba9c" - integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== - dependencies: - buffer "^6.0.3" - module-error "^1.0.1" - level-ws@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" @@ -7153,14 +6706,6 @@ level-ws@^2.0.0: readable-stream "^3.1.0" xtend "^4.0.1" -level@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" - integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ== - dependencies: - browser-level "^1.0.1" - classic-level "^1.2.0" - levelup@3.1.1, levelup@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" @@ -7195,14 +6740,6 @@ levelup@^4.3.2: level-supports "~1.0.0" xtend "~4.0.0" -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -7211,6 +6748,19 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -7282,7 +6832,7 @@ lodash@4.17.20: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4: +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7320,9 +6870,9 @@ loose-envify@^1.0.0: js-tokens "^3.0.0 || ^4.0.0" loupe@^2.3.1: - version "2.3.4" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" - integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== dependencies: get-func-name "^2.0.0" @@ -7336,6 +6886,11 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== + lru-cache@5.1.1, lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -7491,15 +7046,6 @@ memoizee@^0.4.15: next-tick "^1.1.0" timers-ext "^0.1.7" -memory-level@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" - integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og== - dependencies: - abstract-level "^1.0.0" - functional-red-black-tree "^1.0.1" - module-error "^1.0.1" - memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" @@ -7611,11 +7157,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -7648,7 +7189,7 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== -"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.1.1: +"minimatch@2 || 3", minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -7669,13 +7210,6 @@ minimatch@4.2.1: dependencies: brace-expansion "^1.1.7" -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - minimatch@^5.0.1: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" @@ -7683,10 +7217,10 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@~1.2.6: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7, minimist@~1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" @@ -7723,10 +7257,10 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mkdirp@*: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== mkdirp@0.5.5: version "0.5.5" @@ -7742,39 +7276,17 @@ mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5: dependencies: minimist "^1.2.6" -mnemonist@^0.38.0: - version "0.38.5" - resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" - integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== - dependencies: - obliterator "^2.0.0" - -mocha@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.1.0.tgz#dbf1114b7c3f9d0ca5de3133906aea3dfc89ef7a" - integrity sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.2.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - nanoid "3.3.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" mocha@^7.1.1: version "7.2.0" @@ -7841,11 +7353,6 @@ mock-fs@^4.1.0: resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== -module-error@^1.0.1, module-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/module-error/-/module-error-1.0.2.tgz#8d1a48897ca883f47a45816d4fb3e3c6ba404d86" - integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -7915,11 +7422,6 @@ murmur-128@^0.2.1: fmix "^0.1.0" imul "^1.0.0" -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== - nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" @@ -7930,11 +7432,6 @@ nanoid@3.3.1: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -7952,11 +7449,6 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" -napi-macros@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" - integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -8002,13 +7494,20 @@ node-environment-flags@1.0.6: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" -node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@^2.6.1, node-fetch@^2.6.11, node-fetch@^2.6.7: + version "2.6.11" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" + integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== + dependencies: + whatwg-url "^5.0.0" + node-fetch@~1.7.1: version "1.7.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" @@ -8018,14 +7517,9 @@ node-fetch@~1.7.1: is-stream "^1.0.1" node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" - integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg== - -nofilter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-1.0.4.tgz#78d6f4b6a613e7ced8b015cec534625f7667006e" - integrity sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA== + version "4.6.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== nofilter@^3.1.0: version "3.1.0" @@ -8110,10 +7604,10 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.12.2, object-inspect@^1.9.0, object-inspect@~1.12.2: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.12.3, object-inspect@^1.9.0, object-inspect@~1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== object-is@^1.0.1: version "1.1.5" @@ -8160,15 +7654,16 @@ object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz#7965e6437a57278b587383831a9b829455a4bc37" - integrity sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ== +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312" + integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ== dependencies: - array.prototype.reduce "^1.0.4" + array.prototype.reduce "^1.0.5" call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.1" + define-properties "^1.2.0" + es-abstract "^1.21.2" + safe-array-concat "^1.0.0" object.pick@^1.3.0: version "1.3.0" @@ -8210,13 +7705,6 @@ once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== - dependencies: - mimic-fn "^1.0.0" - open@^7.4.2: version "7.4.2" resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" @@ -8225,7 +7713,7 @@ open@^7.4.2: is-docker "^2.0.0" is-wsl "^2.1.1" -optionator@^0.8.1, optionator@^0.8.2: +optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -8285,6 +7773,11 @@ p-cancelable@^2.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== + p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" @@ -8401,13 +7894,15 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: + "@babel/code-frame" "^7.0.0" error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" parse5-htmlparser2-tree-adapter@^7.0.0: version "7.0.0" @@ -8452,24 +7947,25 @@ patch-package@6.2.2: slash "^2.0.0" tmp "^0.0.33" -patch-package@^6.2.2: - version "6.4.7" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.4.7.tgz#2282d53c397909a0d9ef92dae3fdeb558382b148" - integrity sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ== +patch-package@^6.2.2, patch-package@^6.4.7: + version "6.5.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" + integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== dependencies: "@yarnpkg/lockfile" "^1.1.0" - chalk "^2.4.2" + chalk "^4.1.2" cross-spawn "^6.0.5" find-yarn-workspace-root "^2.0.0" - fs-extra "^7.0.1" + fs-extra "^9.0.0" is-ci "^2.0.0" klaw-sync "^6.0.0" - minimist "^1.2.0" + minimist "^1.2.6" open "^7.4.2" rimraf "^2.6.3" semver "^5.6.0" slash "^2.0.0" tmp "^0.0.33" + yaml "^1.10.2" path-browserify@^1.0.0: version "1.0.1" @@ -8498,11 +7994,6 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== - path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -8597,6 +8088,11 @@ pkg-dir@4.2.0: dependencies: find-up "^4.0.0" +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + pollock@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/pollock/-/pollock-0.2.1.tgz#01273ae3542511492d07f1c10fa53f149b37c6ad" @@ -8640,26 +8136,18 @@ prettier-linter-helpers@^1.0.0: fast-diff "^1.1.2" prettier-plugin-solidity@^1.0.0-beta.17: - version "1.0.0-beta.24" - resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.24.tgz#67573ca87098c14f7ccff3639ddd8a4cab2a87eb" - integrity sha512-6JlV5BBTWzmDSq4kZ9PTXc3eLOX7DF5HpbqmmaF+kloyUwOZbJ12hIYsUaZh2fVgZdV2t0vWcvY6qhILhlzgqg== + version "1.1.3" + resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.1.3.tgz#9a35124f578404caf617634a8cab80862d726cba" + integrity sha512-fQ9yucPi2sBbA2U2Xjh6m4isUTJ7S7QLc/XDDsktqqxYfTwdYKJ0EnnywXHwCGAaYbQNK+HIYPL1OemxuMsgeg== dependencies: - "@solidity-parser/parser" "^0.14.3" - emoji-regex "^10.1.0" - escape-string-regexp "^4.0.0" - semver "^7.3.7" + "@solidity-parser/parser" "^0.16.0" + semver "^7.3.8" solidity-comments-extractor "^0.0.7" - string-width "^4.2.3" - -prettier@^1.14.3: - version "1.19.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== -prettier@^2.1.2, prettier@^2.3.2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" - integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== +prettier@^2.1.2, prettier@^2.3.2, prettier@^2.8.3: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== private@^0.1.6, private@^0.1.8: version "0.1.8" @@ -8690,9 +8178,9 @@ promise-to-callback@^1.0.0: set-immediate-shim "^1.0.1" promise@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.2.0.tgz#a1f6280ab67457fbfc8aad2b198c9497e9e5c806" - integrity sha512-+CMAlLHqwRYwBMXKCP+o8ns7DN+xHDUiI+0nArsiJ9y+kJVPLFxEaSw6Ha9s9H0tftxg2Yzl25wqj9G7m5wLZg== + version "8.3.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" + integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== dependencies: asap "~2.0.6" @@ -8790,9 +8278,9 @@ pull-pushable@^2.0.0: integrity sha512-M7dp95enQ2kaHvfCt2+DJfyzgCSpWVR2h2kWYnVsW6ZpxQBx5wOu0QWOvQPVoPnBLUZYitYP2y7HyHkLQNeGXg== pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: - version "3.6.14" - resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.6.14.tgz#529dbd5b86131f4a5ed636fdf7f6af00781357ee" - integrity sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew== + version "3.7.0" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.7.0.tgz#85de0e44ff38a4d2ad08cc43fc458e1922f9bf0b" + integrity sha512-Eco+/R004UaCK2qEDE8vGklcTG2OeZSVm1kTUQNrykEjDwcFXDZhygFDsW49DbXyJMEhHeRL3z5cRVqPAhXlIw== pull-window@^2.1.4: version "2.1.4" @@ -8809,20 +8297,20 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - punycode@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" integrity sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA== +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== puppeteer@^13.7.0: version "13.7.0" @@ -8842,13 +8330,20 @@ puppeteer@^13.7.0: unbzip2-stream "1.4.3" ws "8.5.0" -qs@6.11.0, qs@^6.4.0, qs@^6.7.0, qs@^6.9.4: +qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" +qs@^6.11.0, qs@^6.4.0, qs@^6.7.0, qs@^6.9.4: + version "6.11.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" + integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== + dependencies: + side-channel "^1.0.4" + qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -8863,12 +8358,7 @@ query-string@^5.0.1: object-assign "^4.1.0" strict-uri-encode "^1.0.0" -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - -queue-microtask@^1.2.2, queue-microtask@^1.2.3: +queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== @@ -8903,7 +8393,7 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1, raw-body@^2.4.1: +raw-body@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== @@ -8913,6 +8403,16 @@ raw-body@2.5.1, raw-body@^2.4.1: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@2.5.2, raw-body@^2.4.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -8941,9 +8441,9 @@ readable-stream@^1.0.33: string_decoder "~0.10.x" readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -8953,16 +8453,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.0, readable-stream@^3.4.0, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@^3.1.1: +readable-stream@^3.0.6, readable-stream@^3.1.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -9003,11 +8494,11 @@ rechoir@^0.6.2: resolve "^1.1.6" recursive-readdir@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== + version "2.2.3" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372" + integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA== dependencies: - minimatch "3.0.4" + minimatch "^3.0.5" regenerate@^1.2.1: version "1.4.2" @@ -9037,18 +8528,13 @@ regex-not@^1.0.0, regex-not@^1.0.2: safe-regex "^1.1.0" regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + define-properties "^1.2.0" + functions-have-names "^1.2.3" regexpp@^3.1.0: version "3.2.0" @@ -9174,7 +8660,7 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -resolve-alpn@^1.0.0: +resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== @@ -9207,11 +8693,11 @@ resolve@1.17.0: path-parse "^1.0.6" resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.8.1, resolve@~1.22.1: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.11.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -9229,14 +8715,6 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" @@ -9259,13 +8737,6 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -9295,18 +8766,6 @@ rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: dependencies: bn.js "^5.2.0" -run-async@^2.2.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - -run-parallel-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz#be80e936f5768623a38a963262d6bef8ff11e7ba" - integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw== - dependencies: - queue-microtask "^1.2.2" - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -9319,12 +8778,15 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -rxjs@^6.4.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== +safe-array-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" + integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ== dependencies: - tslib "^1.9.0" + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + has-symbols "^1.0.3" + isarray "^2.0.5" safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" @@ -9425,7 +8887,7 @@ semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -9435,10 +8897,10 @@ semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== +semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: + version "7.5.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" + integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" @@ -9626,15 +9088,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -9674,10 +9127,25 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +sol2uml@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/sol2uml/-/sol2uml-2.2.0.tgz#145b1b85cc2c5d466d596f3426aae4dd4dc946f2" + integrity sha512-JMBvn3ZMT/1egoZjheM4Mh9gQudrlVjFZ1VS0gjQ/eluITT08U6V438Jyku28OuXz42aXNbGS80JuRZo0J7pLg== + dependencies: + "@aduh95/viz.js" "^3.7.0" + "@solidity-parser/parser" "^0.14.3" + axios "^0.27.2" + commander "^9.4.0" + convert-svg-to-png "^0.6.4" + debug "^4.3.4" + ethers "^5.6.9" + js-graph-algorithms "^1.0.18" + klaw "^4.0.1" + sol2uml@^2.5.4: - version "2.5.4" - resolved "https://registry.yarnpkg.com/sol2uml/-/sol2uml-2.5.4.tgz#bef9c7eaf55007c346601806271da893c6743eaa" - integrity sha512-1J2YwO/iwayXTxik59t2/FZtsuFjaiBe/OABH5oTf1yBpUzCh5i6WhV25XeOwe6MEZrBncPRUqSBRBvnjk6KGQ== + version "2.5.6" + resolved "https://registry.yarnpkg.com/sol2uml/-/sol2uml-2.5.6.tgz#7ab18b40dc7b8c0135ae103ec519dd616b550fc2" + integrity sha512-AN0Iu6x61L36mJWlzL3jsBQQ2VzFxdYdpcACUaoO9buM+7VuQICDBel8fG26EkW87Plqui+mxrgqfpFv/Ye2vQ== dependencies: "@aduh95/viz.js" "^3.7.0" "@solidity-parser/parser" "^0.15.0" @@ -9740,31 +9208,34 @@ solhint-plugin-prettier@^0.0.5: prettier-linter-helpers "^1.0.0" solhint@^3.2.0: - version "3.3.7" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.3.7.tgz#b5da4fedf7a0fee954cb613b6c55a5a2b0063aa7" - integrity sha512-NjjjVmXI3ehKkb3aNtRJWw55SUVJ8HMKKodwe0HnejA+k0d2kmhw7jvpa+MCTbcEgt8IWSwx0Hu6aCo/iYOZzQ== - dependencies: - "@solidity-parser/parser" "^0.14.1" - ajv "^6.6.1" - antlr4 "4.7.1" - ast-parents "0.0.1" - chalk "^2.4.2" - commander "2.18.0" - cosmiconfig "^5.0.7" - eslint "^5.6.0" - fast-diff "^1.1.2" - glob "^7.1.3" - ignore "^4.0.6" - js-yaml "^3.12.0" - lodash "^4.17.11" + version "3.4.1" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.4.1.tgz#8ea15b21c13d1be0b53fd46d605a24d0b36a0c46" + integrity sha512-pzZn2RlZhws1XwvLPVSsxfHrwsteFf5eySOhpAytzXwKQYbTCJV6z8EevYDiSVKMpWrvbKpEtJ055CuEmzp4Xg== + dependencies: + "@solidity-parser/parser" "^0.16.0" + ajv "^6.12.6" + antlr4 "^4.11.0" + ast-parents "^0.0.1" + chalk "^4.1.2" + commander "^10.0.0" + cosmiconfig "^8.0.0" + fast-diff "^1.2.0" + glob "^8.0.3" + ignore "^5.2.4" + js-yaml "^4.1.0" + lodash "^4.17.21" + pluralize "^8.0.0" semver "^6.3.0" + strip-ansi "^6.0.1" + table "^6.8.1" + text-table "^0.2.0" optionalDependencies: - prettier "^1.14.3" + prettier "^2.8.3" solidity-ast@^0.4.15: - version "0.4.35" - resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.35.tgz#82e064b14dc989338123264bde2235cad751f128" - integrity sha512-F5bTDLh3rmDxRmLSrs3qt3nvxJprWSEkS7h2KmuXDx7XTfJ6ZKVTV1rtPIYCqJAuPsU/qa8YUeFn7jdOAZcTPA== + version "0.4.49" + resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.49.tgz#ecba89d10c0067845b7848c3a3e8cc61a4fc5b82" + integrity sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ== solidity-comments-extractor@^0.0.7: version "0.0.7" @@ -9853,9 +9324,9 @@ source-map@~0.2.0: amdefine ">=0.0.4" spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + version "3.2.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" + integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -9874,9 +9345,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.12" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779" - integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA== + version "3.0.13" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5" + integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -9957,7 +9428,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.1.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -9983,32 +9454,32 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trim@~1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.6.tgz#824960787db37a9e24711802ed0c1d1c0254f83e" - integrity sha512-8lMR2m+U0VJTPp6JjvJTtGyc4FIGq9CdRt7O9p6T0e6K4vjU+OP+SQJpbe/SBmRcCUIvNUnjsbmY6lnMp8MhsQ== +string.prototype.trim@^1.2.7, string.prototype.trim@~1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== dependencies: call-bind "^1.0.2" define-properties "^1.1.4" - es-abstract "^1.19.5" + es-abstract "^1.20.4" string_decoder@^1.1.1: version "1.3.0" @@ -10076,7 +9547,7 @@ strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed "1.0.0" -strip-json-comments@2.0.1, strip-json-comments@^2.0.1: +strip-json-comments@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== @@ -10164,20 +9635,10 @@ sync-rpc@^1.2.1: dependencies: get-port "^3.1.0" -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -table@^6.0.9, table@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca" - integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA== +table@^6.0.9, table@^6.8.0, table@^6.8.1: + version "6.8.1" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== dependencies: ajv "^8.0.1" lodash.truncate "^4.4.2" @@ -10186,24 +9647,24 @@ table@^6.0.9, table@^6.8.0: strip-ansi "^6.0.1" tape@^4.6.3: - version "4.16.1" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.1.tgz#8d511b3a0be1a30441885972047c1dac822fd9be" - integrity sha512-U4DWOikL5gBYUrlzx+J0oaRedm2vKLFbtA/+BRAXboGWpXO7bMP8ddxlq3Cse2bvXFQ0jZMOj6kk3546mvCdFg== + version "4.16.2" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.16.2.tgz#7565e6af20426565557266e9dda7215869b297b6" + integrity sha512-TUChV+q0GxBBCEbfCYkGLkv8hDJYjMdSWdE0/Lr331sB389dsvFUHNV9ph5iQqKzt8Ss9drzcda/YeexclBFqg== dependencies: call-bind "~1.0.2" deep-equal "~1.1.1" - defined "~1.0.0" + defined "~1.0.1" dotignore "~0.1.2" for-each "~0.3.3" glob "~7.2.3" has "~1.0.3" inherits "~2.0.4" is-regex "~1.1.4" - minimist "~1.2.6" - object-inspect "~1.12.2" + minimist "~1.2.7" + object-inspect "~1.12.3" resolve "~1.22.1" resumer "~0.0.0" - string.prototype.trim "~1.2.6" + string.prototype.trim "~1.2.7" through "~2.3.8" tar-fs@2.1.1: @@ -10283,7 +9744,7 @@ through2@^2.0.3: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.6, through@^2.3.8, through@~2.3.4, through@~2.3.8: +through@^2.3.8, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -10441,7 +9902,7 @@ ts-node@^10.9.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -10587,6 +10048,15 @@ typechain@^5.1.2: prettier "^2.1.2" ts-essentials "^7.0.1" +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -10600,9 +10070,9 @@ typedarray@^0.0.6: integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== typescript@^4.2.2: - version "4.8.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" - integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== + version "4.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== typewise-core@^1.2, typewise-core@^1.2.0: version "1.2.0" @@ -10627,9 +10097,9 @@ typical@^2.6.0, typical@^2.6.1: integrity sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg== uglify-js@^3.1.4: - version "3.17.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.3.tgz#f0feedf019c4510f164099e8d7e72ff2d7304377" - integrity sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg== + version "3.17.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.17.4.tgz#61678cf5fa3f5b7eb789bb345df29afb8257c22c" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== ultron@~1.1.0: version "1.1.1" @@ -10659,10 +10129,10 @@ underscore@1.9.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== -undici@^5.4.0: - version "5.11.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.11.0.tgz#1db25f285821828fc09d3804b9e2e934ae86fc13" - integrity sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw== +undici@^5.14.0, undici@^5.4.0: + version "5.22.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.22.1.tgz#877d512effef2ac8be65e695f3586922e1a57d7b" + integrity sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw== dependencies: busboy "^1.6.0" @@ -10729,12 +10199,12 @@ url-set-query@^1.0.0: integrity sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg== url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== + version "0.11.1" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.1.tgz#26f90f615427eca1b9f4d6a28288c147e2302a32" + integrity sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA== dependencies: - punycode "1.3.2" - querystring "0.2.0" + punycode "^1.4.1" + qs "^6.11.0" use@^3.1.0: version "3.1.1" @@ -10759,17 +10229,19 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util.promisify@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" - integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== + version "1.1.2" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.2.tgz#02b3dbadbb80071eee4c43aed58747afdfc516db" + integrity sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" + call-bind "^1.0.2" + define-properties "^1.2.0" for-each "^0.3.3" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.1" + has-proto "^1.0.1" + has-symbols "^1.0.3" + object.getownpropertydescriptors "^2.1.6" + safe-array-concat "^1.0.0" -util@^0.12.0: +util@^0.12.0, util@^0.12.5: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== @@ -10805,6 +10277,11 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" + integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" @@ -10842,6 +10319,15 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +web3-bzz@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.10.0.tgz#ac74bc71cdf294c7080a79091079192f05c5baed" + integrity sha512-o9IR59io3pDUsXTsps5pO5hW1D5zBmg46iNc2t4j2DkaYHNdDLwk2IP9ukoM2wg47QILfPEJYzhTfkS/CcX0KA== + dependencies: + "@types/node" "^12.12.6" + got "12.1.0" + swarm-js "^0.1.40" + web3-bzz@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" @@ -10861,6 +10347,14 @@ web3-bzz@1.7.4: got "9.6.0" swarm-js "^0.1.40" +web3-core-helpers@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.10.0.tgz#1016534c51a5df77ed4f94d1fcce31de4af37fad" + integrity sha512-pIxAzFDS5vnbXvfvLSpaA1tfRykAe9adw43YCKsEYQwH0gCLL0kMLkaCX3q+Q8EVmAh+e1jWL/nl9U0de1+++g== + dependencies: + web3-eth-iban "1.10.0" + web3-utils "1.10.0" + web3-core-helpers@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" @@ -10878,6 +10372,17 @@ web3-core-helpers@1.7.4: web3-eth-iban "1.7.4" web3-utils "1.7.4" +web3-core-method@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.10.0.tgz#82668197fa086e8cc8066742e35a9d72535e3412" + integrity sha512-4R700jTLAMKDMhQ+nsVfIXvH6IGJlJzGisIfMKWAIswH31h5AZz7uDUW2YctI+HrYd+5uOAlS4OJeeT9bIpvkA== + dependencies: + "@ethersproject/transactions" "^5.6.2" + web3-core-helpers "1.10.0" + web3-core-promievent "1.10.0" + web3-core-subscriptions "1.10.0" + web3-utils "1.10.0" + web3-core-method@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" @@ -10901,6 +10406,13 @@ web3-core-method@1.7.4: web3-core-subscriptions "1.7.4" web3-utils "1.7.4" +web3-core-promievent@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.10.0.tgz#cbb5b3a76b888df45ed3a8d4d8d4f54ccb66a37b" + integrity sha512-68N7k5LWL5R38xRaKFrTFT2pm2jBNFaM4GioS00YjAKXRQ3KjmhijOMG3TICz6Aa5+6GDWYelDNx21YAeZ4YTg== + dependencies: + eventemitter3 "4.0.4" + web3-core-promievent@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" @@ -10915,6 +10427,17 @@ web3-core-promievent@1.7.4: dependencies: eventemitter3 "4.0.4" +web3-core-requestmanager@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.10.0.tgz#4b34f6e05837e67c70ff6f6993652afc0d54c340" + integrity sha512-3z/JKE++Os62APml4dvBM+GAuId4h3L9ckUrj7ebEtS2AR0ixyQPbrBodgL91Sv7j7cQ3Y+hllaluqjguxvSaQ== + dependencies: + util "^0.12.5" + web3-core-helpers "1.10.0" + web3-providers-http "1.10.0" + web3-providers-ipc "1.10.0" + web3-providers-ws "1.10.0" + web3-core-requestmanager@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" @@ -10937,6 +10460,14 @@ web3-core-requestmanager@1.7.4: web3-providers-ipc "1.7.4" web3-providers-ws "1.7.4" +web3-core-subscriptions@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.10.0.tgz#b534592ee1611788fc0cb0b95963b9b9b6eacb7c" + integrity sha512-HGm1PbDqsxejI075gxBc5OSkwymilRWZufIy9zEpnWKNmfbuv5FfHgW1/chtJP6aP3Uq2vHkvTDl3smQBb8l+g== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.10.0" + web3-core-subscriptions@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" @@ -10954,6 +10485,19 @@ web3-core-subscriptions@1.7.4: eventemitter3 "4.0.4" web3-core-helpers "1.7.4" +web3-core@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.10.0.tgz#9aa07c5deb478cf356c5d3b5b35afafa5fa8e633" + integrity sha512-fWySwqy2hn3TL89w5TM8wXF1Z2Q6frQTKHWmP0ppRQorEK8NcHJRfeMiv/mQlSKoTS1F6n/nv2uyZsixFycjYQ== + dependencies: + "@types/bn.js" "^5.1.1" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.10.0" + web3-core-method "1.10.0" + web3-core-requestmanager "1.10.0" + web3-utils "1.10.0" + web3-core@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" @@ -10980,6 +10524,14 @@ web3-core@1.7.4: web3-core-requestmanager "1.7.4" web3-utils "1.7.4" +web3-eth-abi@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.10.0.tgz#53a7a2c95a571e205e27fd9e664df4919483cce1" + integrity sha512-cwS+qRBWpJ43aI9L3JS88QYPfFcSJJ3XapxOQ4j40v6mk7ATpA8CVK1vGTzpihNlOfMVRBkR95oAj7oL6aiDOg== + dependencies: + "@ethersproject/abi" "^5.6.3" + web3-utils "1.10.0" + web3-eth-abi@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" @@ -10997,6 +10549,22 @@ web3-eth-abi@1.7.4: "@ethersproject/abi" "^5.6.3" web3-utils "1.7.4" +web3-eth-accounts@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.10.0.tgz#2942beca0a4291455f32cf09de10457a19a48117" + integrity sha512-wiq39Uc3mOI8rw24wE2n15hboLE0E9BsQLdlmsL4Zua9diDS6B5abXG0XhFcoNsXIGMWXVZz4TOq3u4EdpXF/Q== + dependencies: + "@ethereumjs/common" "2.5.0" + "@ethereumjs/tx" "3.3.2" + eth-lib "0.2.8" + ethereumjs-util "^7.1.5" + scrypt-js "^3.0.1" + uuid "^9.0.0" + web3-core "1.10.0" + web3-core-helpers "1.10.0" + web3-core-method "1.10.0" + web3-utils "1.10.0" + web3-eth-accounts@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" @@ -11031,6 +10599,20 @@ web3-eth-accounts@1.7.4: web3-core-method "1.7.4" web3-utils "1.7.4" +web3-eth-contract@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.10.0.tgz#8e68c7654576773ec3c91903f08e49d0242c503a" + integrity sha512-MIC5FOzP/+2evDksQQ/dpcXhSqa/2hFNytdl/x61IeWxhh6vlFeSjq0YVTAyIzdjwnL7nEmZpjfI6y6/Ufhy7w== + dependencies: + "@types/bn.js" "^5.1.1" + web3-core "1.10.0" + web3-core-helpers "1.10.0" + web3-core-method "1.10.0" + web3-core-promievent "1.10.0" + web3-core-subscriptions "1.10.0" + web3-eth-abi "1.10.0" + web3-utils "1.10.0" + web3-eth-contract@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" @@ -11060,6 +10642,20 @@ web3-eth-contract@1.7.4: web3-eth-abi "1.7.4" web3-utils "1.7.4" +web3-eth-ens@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.10.0.tgz#96a676524e0b580c87913f557a13ed810cf91cd9" + integrity sha512-3hpGgzX3qjgxNAmqdrC2YUQMTfnZbs4GeLEmy8aCWziVwogbuqQZ+Gzdfrym45eOZodk+lmXyLuAdqkNlvkc1g== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + web3-core "1.10.0" + web3-core-helpers "1.10.0" + web3-core-promievent "1.10.0" + web3-eth-abi "1.10.0" + web3-eth-contract "1.10.0" + web3-utils "1.10.0" + web3-eth-ens@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" @@ -11089,6 +10685,14 @@ web3-eth-ens@1.7.4: web3-eth-contract "1.7.4" web3-utils "1.7.4" +web3-eth-iban@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.10.0.tgz#5a46646401965b0f09a4f58e7248c8a8cd22538a" + integrity sha512-0l+SP3IGhInw7Q20LY3IVafYEuufo4Dn75jAHT7c2aDJsIolvf2Lc6ugHkBajlwUneGfbRQs/ccYPQ9JeMUbrg== + dependencies: + bn.js "^5.2.1" + web3-utils "1.10.0" + web3-eth-iban@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" @@ -11105,6 +10709,18 @@ web3-eth-iban@1.7.4: bn.js "^5.2.1" web3-utils "1.7.4" +web3-eth-personal@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.10.0.tgz#94d525f7a29050a0c2a12032df150ac5ea633071" + integrity sha512-anseKn98w/d703eWq52uNuZi7GhQeVjTC5/svrBWEKob0WZ5kPdo+EZoFN0sp5a5ubbrk/E0xSl1/M5yORMtpg== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.10.0" + web3-core-helpers "1.10.0" + web3-core-method "1.10.0" + web3-net "1.10.0" + web3-utils "1.10.0" + web3-eth-personal@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" @@ -11129,6 +10745,24 @@ web3-eth-personal@1.7.4: web3-net "1.7.4" web3-utils "1.7.4" +web3-eth@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.10.0.tgz#38b905e2759697c9624ab080cfcf4e6c60b3a6cf" + integrity sha512-Z5vT6slNMLPKuwRyKGbqeGYC87OAy8bOblaqRTgg94CXcn/mmqU7iPIlG4506YdcdK3x6cfEDG7B6w+jRxypKA== + dependencies: + web3-core "1.10.0" + web3-core-helpers "1.10.0" + web3-core-method "1.10.0" + web3-core-subscriptions "1.10.0" + web3-eth-abi "1.10.0" + web3-eth-accounts "1.10.0" + web3-eth-contract "1.10.0" + web3-eth-ens "1.10.0" + web3-eth-iban "1.10.0" + web3-eth-personal "1.10.0" + web3-net "1.10.0" + web3-utils "1.10.0" + web3-eth@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" @@ -11166,6 +10800,15 @@ web3-eth@1.7.4: web3-net "1.7.4" web3-utils "1.7.4" +web3-net@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.10.0.tgz#be53e7f5dafd55e7c9013d49c505448b92c9c97b" + integrity sha512-NLH/N3IshYWASpxk4/18Ge6n60GEvWBVeM8inx2dmZJVmRI6SJIlUxbL8jySgiTn3MMZlhbdvrGo8fpUW7a1GA== + dependencies: + web3-core "1.10.0" + web3-core-method "1.10.0" + web3-utils "1.10.0" + web3-net@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" @@ -11210,6 +10853,16 @@ web3-provider-engine@14.2.1: xhr "^2.2.0" xtend "^4.0.1" +web3-providers-http@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.10.0.tgz#864fa48675e7918c9a4374e5f664b32c09d0151b" + integrity sha512-eNr965YB8a9mLiNrkjAWNAPXgmQWfpBfkkn7tpEFlghfww0u3I0tktMZiaToJVcL2+Xq+81cxbkpeWJ5XQDwOA== + dependencies: + abortcontroller-polyfill "^1.7.3" + cross-fetch "^3.1.4" + es6-promise "^4.2.8" + web3-core-helpers "1.10.0" + web3-providers-http@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" @@ -11226,6 +10879,14 @@ web3-providers-http@1.7.4: web3-core-helpers "1.7.4" xhr2-cookies "1.1.0" +web3-providers-ipc@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.10.0.tgz#9747c7a6aee96a51488e32fa7c636c3460b39889" + integrity sha512-OfXG1aWN8L1OUqppshzq8YISkWrYHaATW9H8eh0p89TlWMc1KZOL9vttBuaBEi96D/n0eYDn2trzt22bqHWfXA== + dependencies: + oboe "2.1.5" + web3-core-helpers "1.10.0" + web3-providers-ipc@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" @@ -11243,6 +10904,15 @@ web3-providers-ipc@1.7.4: oboe "2.1.5" web3-core-helpers "1.7.4" +web3-providers-ws@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.10.0.tgz#cb0b87b94c4df965cdf486af3a8cd26daf3975e5" + integrity sha512-sK0fNcglW36yD5xjnjtSGBnEtf59cbw4vZzJ+CmOWIKGIR96mP5l684g0WD0Eo+f4NQc2anWWXG74lRc9OVMCQ== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.10.0" + websocket "^1.0.32" + web3-providers-ws@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" @@ -11262,6 +10932,16 @@ web3-providers-ws@1.7.4: web3-core-helpers "1.7.4" websocket "^1.0.32" +web3-shh@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.10.0.tgz#c2979b87e0f67a7fef2ce9ee853bd7bfbe9b79a8" + integrity sha512-uNUUuNsO2AjX41GJARV9zJibs11eq6HtOe6Wr0FtRUcj8SN6nHeYIzwstAvJ4fXA53gRqFMTxdntHEt9aXVjpg== + dependencies: + web3-core "1.10.0" + web3-core-method "1.10.0" + web3-core-subscriptions "1.10.0" + web3-net "1.10.0" + web3-shh@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" @@ -11282,6 +10962,19 @@ web3-shh@1.7.4: web3-core-subscriptions "1.7.4" web3-net "1.7.4" +web3-utils@1.10.0, web3-utils@^1.0.0-beta.31, web3-utils@^1.3.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" + integrity sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg== + dependencies: + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + web3-utils@1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" @@ -11309,18 +11002,18 @@ web3-utils@1.7.4: randombytes "^2.1.0" utf8 "3.0.0" -web3-utils@^1.0.0-beta.31, web3-utils@^1.3.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.8.0.tgz#0a506f8c6af9a2ad6ba79689892662769534fc03" - integrity sha512-7nUIl7UWpLVka2f09CMbKOSEvorvHnaugIabU4mj7zfMvm0tSByLcEu3eyV9qgS11qxxLuOkzBIwCstTflhmpQ== +web3@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.10.0.tgz#2fde0009f59aa756c93e07ea2a7f3ab971091274" + integrity sha512-YfKY9wSkGcM8seO+daR89oVTcbu18NsVfvOngzqMYGUU0pPSQmE57qQDvQzUeoIOHAnXEBNzrhjQJmm8ER0rng== dependencies: - bn.js "^5.2.1" - ethereum-bloom-filters "^1.0.6" - ethereumjs-util "^7.1.0" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - utf8 "3.0.0" + web3-bzz "1.10.0" + web3-core "1.10.0" + web3-eth "1.10.0" + web3-eth-personal "1.10.0" + web3-net "1.10.0" + web3-shh "1.10.0" + web3-utils "1.10.0" web3@1.2.11: version "1.2.11" @@ -11407,21 +11100,21 @@ which-module@^1.0.0: integrity sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ== which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== -which-typed-array@^1.1.2: - version "1.1.8" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.8.tgz#0cfd53401a6f334d90ed1125754a42ed663eb01f" - integrity sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw== +which-typed-array@^1.1.2, which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== dependencies: available-typed-arrays "^1.0.5" call-bind "^1.0.2" - es-abstract "^1.20.0" for-each "^0.3.3" + gopd "^1.0.1" has-tostringtag "^1.0.0" - is-typed-array "^1.1.9" + is-typed-array "^1.1.10" which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: version "1.3.1" @@ -11464,11 +11157,6 @@ workerpool@6.2.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== - wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -11500,13 +11188,6 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - ws@7.4.6: version "7.4.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" @@ -11622,6 +11303,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + yargs-parser@13.1.2, yargs-parser@^13.1.0, yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" From 51f19950c6609c8fa674e744daae552e212ac5cb Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 27 Jun 2023 11:23:50 +0200 Subject: [PATCH 078/163] In test token implementation, re-set native token allowance to 0 --- contracts/tokenbridge/test/TestCustomTokenL1.sol | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/contracts/tokenbridge/test/TestCustomTokenL1.sol b/contracts/tokenbridge/test/TestCustomTokenL1.sol index f33216b6c1..cc2cc33e51 100644 --- a/contracts/tokenbridge/test/TestCustomTokenL1.sol +++ b/contracts/tokenbridge/test/TestCustomTokenL1.sol @@ -151,10 +151,11 @@ contract TestOrbitCustomTokenL1 is TestCustomTokenL1 { bool prev = shouldRegisterGateway; shouldRegisterGateway = true; + address inbox = IOrbitGatewayRouter(router).inbox(); + address bridge = address(IInbox(inbox).bridge()); + // transfer fees from user to here, and approve router to use it { - address inbox = IOrbitGatewayRouter(router).inbox(); - address bridge = address(IInbox(inbox).bridge()); address nativeToken = IERC20Bridge(bridge).nativeToken(); IERC20(nativeToken).safeTransferFrom( @@ -184,6 +185,14 @@ contract TestOrbitCustomTokenL1 is TestCustomTokenL1 { valueForRouter ); + // reset allowance back to 0 in case not all approved native tokens are spent + { + address nativeToken = IERC20Bridge(bridge).nativeToken(); + + IERC20(nativeToken).approve(router, 0); + IERC20(nativeToken).approve(gateway, 0); + } + shouldRegisterGateway = prev; } } From 4c420083ff97a7f7f3387a6c93667d4d25b77fdb Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 27 Jun 2023 16:02:50 +0200 Subject: [PATCH 079/163] Add Hardhat test which checks token bridge is properly deployed --- .gitignore | 1 + test-e2e/tokenBridgeDeploymentTest.ts | 356 ++++++++++++++++++++++++++ 2 files changed, 357 insertions(+) create mode 100644 test-e2e/tokenBridgeDeploymentTest.ts diff --git a/.gitignore b/.gitignore index f4fbcf4c70..9058922686 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ build artifacts deployment.json test/storage/*-old.dot +network.json \ No newline at end of file diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts new file mode 100644 index 0000000000..bcfd782e16 --- /dev/null +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -0,0 +1,356 @@ +import { L1Network, L2Network, getL1Network, getL2Network } from '@arbitrum/sdk' +import { JsonRpcProvider } from '@ethersproject/providers' +import { + BeaconProxyFactory__factory, + L1CustomGateway, + L1CustomGateway__factory, + L1ERC20Gateway, + L1ERC20Gateway__factory, + L1GatewayRouter, + L1GatewayRouter__factory, + L1WethGateway, + L1WethGateway__factory, + L2CustomGateway, + L2CustomGateway__factory, + L2ERC20Gateway, + L2ERC20Gateway__factory, + L2GatewayRouter, + L2GatewayRouter__factory, + L2WethGateway, + L2WethGateway__factory, +} from '../build/types' +import path from 'path' +import fs from 'fs' +import { + addCustomNetwork, + l1Networks, + l2Networks, +} from '@arbitrum/sdk/dist/lib/dataEntities/networks' +import { expect } from 'chai' +import { ethers } from 'hardhat' + +const config = { + arbUrl: 'http://localhost:8547', + ethUrl: 'http://localhost:8545', +} + +let _l1Network: L1Network +let _l2Network: L2Network + +let _l1Provider: JsonRpcProvider +let _l2Provider: JsonRpcProvider + +describe('tokenBridge', () => { + // configure token bridge + before(async function () {}) + + it('should have deployed token bridge contracts', async function () { + const { l1Network, l1Provider, l2Network, l2Provider } = + await getProvidersAndSetupNetworks({ + l1Url: config.ethUrl, + l2Url: config.arbUrl, + networkFilename: './network.json', + }) + + _l1Network = l1Network + _l2Network = l2Network + + _l1Provider = l1Provider + _l2Provider = l2Provider + + //// L1 checks + + checkL1RouterInitialization( + L1GatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + l1Provider + ) + ) + + checkL1StandardGatewayInitialization( + L1ERC20Gateway__factory.connect( + _l2Network.tokenBridge.l1ERC20Gateway, + l1Provider + ) + ) + + checkL1CustomGatewayInitialization( + L1CustomGateway__factory.connect( + _l2Network.tokenBridge.l1CustomGateway, + l1Provider + ) + ) + + checkL1WethGatewayInitialization( + L1WethGateway__factory.connect( + _l2Network.tokenBridge.l1WethGateway, + l1Provider + ) + ) + + //// L2 checks + + checkL2RouterInitialization( + L2GatewayRouter__factory.connect( + _l2Network.tokenBridge.l2GatewayRouter, + l2Provider + ) + ) + + checkL2StandardGatewayInitialization( + L2ERC20Gateway__factory.connect( + _l2Network.tokenBridge.l2ERC20Gateway, + l2Provider + ) + ) + + checkL2CustomGatewayInitialization( + L2CustomGateway__factory.connect( + _l2Network.tokenBridge.l2CustomGateway, + l2Provider + ) + ) + + checkL2WethGatewayInitialization( + L2WethGateway__factory.connect( + _l2Network.tokenBridge.l2WethGateway, + l2Provider + ) + ) + }) +}) + +//// L1 contracts + +async function checkL1RouterInitialization(l1Router: L1GatewayRouter) { + expect((await l1Router.defaultGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1ERC20Gateway.toLowerCase() + ) + + // TODO - generic way to check owner + // expect((await l1Router.owner()).toLowerCase()).to.be.eq( + // (await l1Signer.getAddress(),º.toLowerCase() + // ) + + expect((await l1Router.inbox()).toLowerCase()).to.be.eq( + _l2Network.ethBridge.inbox.toLowerCase() + ) + + expect((await l1Router.router()).toLowerCase()).to.be.eq( + ethers.constants.AddressZero + ) + + expect((await l1Router.counterpartGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() + ) +} + +async function checkL1StandardGatewayInitialization( + l1ERC20Gateway: L1ERC20Gateway +) { + expect((await l1ERC20Gateway.counterpartGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2ERC20Gateway.toLowerCase() + ) + + expect((await l1ERC20Gateway.router()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1GatewayRouter.toLowerCase() + ) + + expect((await l1ERC20Gateway.inbox()).toLowerCase()).to.be.eq( + _l2Network.ethBridge.inbox.toLowerCase() + ) + + expect((await l1ERC20Gateway.l2BeaconProxyFactory()).toLowerCase()).to.be.eq( + await L2ERC20Gateway__factory.connect( + await l1ERC20Gateway.counterpartGateway(), + _l2Provider + ).beaconProxyFactory() + ) + + expect((await l1ERC20Gateway.cloneableProxyHash()).toLowerCase()).to.be.eq( + ( + await BeaconProxyFactory__factory.connect( + await l1ERC20Gateway.cloneableProxyHash(), + _l2Provider + ).cloneableProxyHash() + ).toLowerCase() + ) + + expect((await l1ERC20Gateway.whitelist()).toLowerCase()).to.be.eq( + ethers.constants.AddressZero + ) +} + +async function checkL1CustomGatewayInitialization( + l1CustomGateway: L1CustomGateway +) { + expect((await l1CustomGateway.counterpartGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2CustomGateway.toLowerCase() + ) + + expect((await l1CustomGateway.router()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1GatewayRouter.toLowerCase() + ) + + expect((await l1CustomGateway.inbox()).toLowerCase()).to.be.eq( + _l2Network.ethBridge.inbox.toLowerCase() + ) + + // TODO + // owner check + + expect((await l1CustomGateway.whitelist()).toLowerCase()).to.be.eq( + ethers.constants.AddressZero + ) +} + +async function checkL1WethGatewayInitialization(l1WethGateway: L1WethGateway) { + expect((await l1WethGateway.counterpartGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2WethGateway.toLowerCase() + ) + + expect((await l1WethGateway.router()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1GatewayRouter.toLowerCase() + ) + + expect((await l1WethGateway.inbox()).toLowerCase()).to.be.eq( + _l2Network.ethBridge.inbox.toLowerCase() + ) + + expect((await l1WethGateway.l1Weth()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1Weth.toLowerCase() + ) + + expect((await l1WethGateway.l2Weth()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2Weth.toLowerCase() + ) +} + +//// L2 contracts + +async function checkL2RouterInitialization(l2Router: L2GatewayRouter) { + expect((await l2Router.defaultGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2ERC20Gateway.toLowerCase() + ) + + expect((await l2Router.router()).toLowerCase()).to.be.eq( + ethers.constants.AddressZero + ) + + expect((await l2Router.counterpartGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1GatewayRouter.toLowerCase() + ) +} + +async function checkL2StandardGatewayInitialization( + l2ERC20Gateway: L2ERC20Gateway +) { + expect((await l2ERC20Gateway.counterpartGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1ERC20Gateway.toLowerCase() + ) + + expect((await l2ERC20Gateway.router()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() + ) + + expect((await l2ERC20Gateway.beaconProxyFactory()).toLowerCase()).to.be.eq( + await L1ERC20Gateway__factory.connect( + await l2ERC20Gateway.counterpartGateway(), + _l1Provider + ).l2BeaconProxyFactory() + ) + + expect((await l2ERC20Gateway.cloneableProxyHash()).toLowerCase()).to.be.eq( + ( + await L1ERC20Gateway__factory.connect( + await l2ERC20Gateway.counterpartGateway(), + _l1Provider + ).cloneableProxyHash() + ).toLowerCase() + ) +} + +async function checkL2CustomGatewayInitialization( + l2CustomGateway: L2CustomGateway +) { + expect((await l2CustomGateway.counterpartGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1CustomGateway.toLowerCase() + ) + + expect((await l2CustomGateway.router()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() + ) +} + +export const getProvidersAndSetupNetworks = async (setupConfig: { + l1Url: string + l2Url: string + networkFilename?: string +}): Promise<{ + l1Network: L1Network + l2Network: L2Network + l1Provider: JsonRpcProvider + l2Provider: JsonRpcProvider +}> => { + const l1Provider = new JsonRpcProvider(setupConfig.l1Url) + const l2Provider = new JsonRpcProvider(setupConfig.l2Url) + + if (setupConfig.networkFilename) { + // check if theres an existing network available + const localNetworkFile = path.join( + __dirname, + '..', + setupConfig.networkFilename + ) + if (fs.existsSync(localNetworkFile)) { + const { l1Network, l2Network } = JSON.parse( + fs.readFileSync(localNetworkFile).toString() + ) as { + l1Network: L1Network + l2Network: L2Network + } + + const existingL1Network = l1Networks[l1Network.chainID.toString()] + const existingL2Network = l2Networks[l2Network.chainID.toString()] + if (!existingL2Network) { + addCustomNetwork({ + // dont add the l1 network if it's already been added + customL1Network: existingL1Network ? undefined : l1Network, + customL2Network: l2Network, + }) + } + + return { + l1Network, + l1Provider, + l2Network, + l2Provider, + } + } else throw Error(`Missing file ${localNetworkFile}`) + } else { + return { + l1Network: await getL1Network(l1Provider), + l1Provider, + l2Network: await getL2Network(l2Provider), + l2Provider, + } + } +} + +async function checkL2WethGatewayInitialization(l2WethGateway: L2WethGateway) { + expect((await l2WethGateway.counterpartGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1WethGateway.toLowerCase() + ) + + expect((await l2WethGateway.router()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() + ) + + expect((await l2WethGateway.l1Weth()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1Weth.toLowerCase() + ) + + expect((await l2WethGateway.l2Weth()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2Weth.toLowerCase() + ) +} From eb3cfb3f3ef9bf0a759a5f3bf2fd9f029fa36477 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 29 Jun 2023 12:12:44 +0200 Subject: [PATCH 080/163] Add 1st implementation of token bridge L1&L2 factories --- .../arbitrum/L2TokenBridgeFactory.sol | 68 ++++ .../ethereum/L1TokenBridgeCreator.sol | 92 +++++ package.json | 1 + .../tokenBridgeDeployerViaFactories.ts | 337 ++++++++++++++++++ 4 files changed, 498 insertions(+) create mode 100644 contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol create mode 100644 contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol create mode 100644 scripts/local-deployment/tokenBridgeDeployerViaFactories.ts diff --git a/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol new file mode 100644 index 0000000000..11429c8583 --- /dev/null +++ b/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol @@ -0,0 +1,68 @@ +pragma solidity ^0.8.0; + +import { L2GatewayRouter } from "./gateway/L2GatewayRouter.sol"; +import { L2ERC20Gateway } from "./gateway/L2ERC20Gateway.sol"; +import { L2CustomGateway } from "./gateway/L2CustomGateway.sol"; +import { StandardArbERC20 } from "./StandardArbERC20.sol"; +import { BeaconProxyFactory } from "../libraries/ClonableBeaconProxy.sol"; +import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +contract L2TokenBridgeFactory { + L2GatewayRouter public router; + L2ERC20Gateway public standardGateway; + L2CustomGateway public customGateway; + UpgradeableBeacon public beacon; + BeaconProxyFactory public beaconProxyFactory; + + event OrbitL2TokenBridgeCreated( + address router, + address standardGateway, + address customGateway, + address beaconProxyFactory, + address proxyAdmin + ); + + constructor() { + address proxyAdmin = address(new ProxyAdmin()); + + // create router/gateways + router = L2GatewayRouter(_deployBehindProxy(address(new L2GatewayRouter()), proxyAdmin)); + standardGateway = L2ERC20Gateway( + _deployBehindProxy(address(new L2ERC20Gateway()), proxyAdmin) + ); + customGateway = L2CustomGateway( + _deployBehindProxy(address(new L2CustomGateway()), proxyAdmin) + ); + + // create and init beacon + StandardArbERC20 standardArbERC20 = new StandardArbERC20(); + beacon = new UpgradeableBeacon(address(standardArbERC20)); + beaconProxyFactory = new BeaconProxyFactory(); + beaconProxyFactory.initialize(address(beacon)); + + emit OrbitL2TokenBridgeCreated( + address(router), + address(standardGateway), + address(customGateway), + address(beaconProxyFactory), + proxyAdmin + ); + } + + function initTokenBridge( + address l1Router, + address l1StandardGateway, + address l1CustomGateway + ) external { + //// init router/gateways + router.initialize(l1Router, address(standardGateway)); + standardGateway.initialize(l1StandardGateway, address(router), address(beaconProxyFactory)); + customGateway.initialize(l1CustomGateway, address(router)); + } + + function _deployBehindProxy(address logic, address proxyAdmin) internal returns (address) { + return address(new TransparentUpgradeableProxy(logic, proxyAdmin, bytes(""))); + } +} diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol new file mode 100644 index 0000000000..d3f716823d --- /dev/null +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol @@ -0,0 +1,92 @@ +pragma solidity ^0.8.0; + +import { L1GatewayRouter } from "./gateway/L1GatewayRouter.sol"; +import { L1ERC20Gateway } from "./gateway/L1ERC20Gateway.sol"; +import { L1CustomGateway } from "./gateway/L1CustomGateway.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; + +contract L1TokenBridgeCreator is Ownable { + event OrbitTokenBridgeCreated( + address router, + address standardGateway, + address customGateway, + address proxyAdmin + ); + event OrbitTokenBridgeTemplatesUpdated(); + + L1GatewayRouter public routerTemplate; + L1ERC20Gateway public standardGatewayTemplate; + L1CustomGateway public customGatewayTemplate; + + constructor() Ownable() {} + + function setTemplates( + L1GatewayRouter _router, + L1ERC20Gateway _standardGateway, + L1CustomGateway _customGateway + ) external onlyOwner { + routerTemplate = _router; + standardGatewayTemplate = _standardGateway; + customGatewayTemplate = _customGateway; + emit OrbitTokenBridgeTemplatesUpdated(); + } + + function createTokenBridge() external { + address proxyAdmin = address(new ProxyAdmin()); + + L1GatewayRouter router = L1GatewayRouter( + address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes(""))) + ); + L1ERC20Gateway standardGateway = L1ERC20Gateway( + address( + new TransparentUpgradeableProxy( + address(standardGatewayTemplate), + proxyAdmin, + bytes("") + ) + ) + ); + L1CustomGateway customGateway = L1CustomGateway( + address( + new TransparentUpgradeableProxy( + address(customGatewayTemplate), + proxyAdmin, + bytes("") + ) + ) + ); + + emit OrbitTokenBridgeCreated( + address(router), + address(standardGateway), + address(customGateway), + proxyAdmin + ); + } + + function initTokenBridge( + L1GatewayRouter router, + L1ERC20Gateway standardGateway, + L1CustomGateway customGateway, + address owner, + address inbox, + address l2Router, + address l2StandardGateway, + address l2CustomGateway, + bytes32 cloneableProxyHash, + address l2BeaconProxyFactory + ) external { + /// dependencies - l2Router, l2StandardGateway, l2CustomGateway, cloneableProxyHash, l2BeaconProxyFactory, owner, inbox + router.initialize(owner, address(standardGateway), address(0), l2Router, inbox); + standardGateway.initialize( + l2StandardGateway, + address(router), + inbox, + cloneableProxyHash, + l2BeaconProxyFactory + ); + customGateway.initialize(l2CustomGateway, address(router), inbox, owner); + } +} diff --git a/package.json b/package.json index 618025c558..510aa8df86 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "test:l2": "hardhat test test/*.l2.ts", "test:storage": "./scripts/storage_layout_test.bash", "test:deploy:tokenbridge": "ts-node ./scripts/local-deployment/tokenBridgeDeployer.ts", + "test:deploy:tokenbridgeViaFactories": "ts-node ./scripts/local-deployment/tokenBridgeDeployerViaFactories.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", diff --git a/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts b/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts new file mode 100644 index 0000000000..79f15f7608 --- /dev/null +++ b/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts @@ -0,0 +1,337 @@ +import { Contract, Signer, Wallet, ethers } from 'ethers' +import { + BeaconProxyFactory__factory, + L1CustomGateway__factory, + L1ERC20Gateway__factory, + L1GatewayRouter__factory, + L1TokenBridgeCreator__factory, + L2TokenBridgeFactory__factory, +} from '../../build/types' +import { JsonRpcProvider } from '@ethersproject/providers' +import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' +import { execSync } from 'child_process' +import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' +import * as fs from 'fs' + +export const setupTokenBridge = async ( + l1Deployer: Signer, + l2Deployer: Signer, + l1Url: string, + l2Url: string +) => { + const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( + l1Url, + l2Url + ) + + await bridgeFundsToL2Deployer(l1Deployer, coreL2Network.ethBridge.inbox) + + const deployedContracts = await deployTokenBridgeAndInit( + l1Deployer, + l2Deployer, + coreL2Network.ethBridge.inbox + ) + + const l2Network: L2Network = { + ...coreL2Network, + tokenBridge: { + l1CustomGateway: deployedContracts.l1CustomGateway, + l1ERC20Gateway: deployedContracts.l1StandardGateway, + l1GatewayRouter: deployedContracts.l1Router, + l1MultiCall: '', + l1ProxyAdmin: deployedContracts.l1ProxyAdmin, + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: deployedContracts.l2CustomGateway, + l2ERC20Gateway: deployedContracts.l2StandardGateway, + l2GatewayRouter: deployedContracts.l2Router, + l2Multicall: '', + l2ProxyAdmin: deployedContracts.l2ProxyAdmin, + l2Weth: '', + l2WethGateway: '', + }, + } + + addCustomNetwork({ + customL1Network: l1Network, + customL2Network: l2Network, + }) + + return { + l1Network, + l2Network, + } +} + +/** + * Deploy all the L1 and L2 contracts and do the initialization. + * + * @param l1Signer + * @param l2Signer + * @param inboxAddress + * @returns + */ +export const deployTokenBridgeAndInit = async ( + l1Signer: Signer, + l2Signer: Signer, + inboxAddress: string +) => { + // deploy L1 side + const l1TokenBridgeCreator = await deployTokenBridgeFactory(l1Signer) + + const receipt = await (await l1TokenBridgeCreator.createTokenBridge()).wait() + + const iface = l1TokenBridgeCreator.interface + const eventFragment = iface.getEvent('OrbitTokenBridgeCreated') + const parsedLog = receipt.logs + .filter( + (curr: any) => curr.topics[0] === iface.getEventTopic(eventFragment) + ) + .map((curr: any) => iface.parseLog(curr)) + const { + router: l1Router, + standardGateway: l1StandardGateway, + customGateway: l1CustomGateway, + proxyAdmin: l1ProxyAdmin, + } = parsedLog[0].args + + // deploy L2 side + const l2TokenBridgeFactory = await new L2TokenBridgeFactory__factory( + l2Signer + ).deploy() + await l2TokenBridgeFactory.deployed() + const l2Receipt = await l2Signer.provider!.getTransactionReceipt( + l2TokenBridgeFactory.deployTransaction.hash + ) + + const l2Iface = l2TokenBridgeFactory.interface + const l2Event = l2Iface.getEvent('OrbitL2TokenBridgeCreated') + const parsedL2Log = l2Receipt.logs + .filter((curr: any) => curr.topics[0] === l2Iface.getEventTopic(l2Event)) + .map((curr: any) => l2Iface.parseLog(curr)) + const { + router: l2Router, + standardGateway: l2StandardGateway, + customGateway: l2CustomGateway, + beaconProxyFactory, + proxyAdmin: l2ProxyAdmin, + } = parsedL2Log[0].args + + // init L1 side + const cloneableProxyHash = await BeaconProxyFactory__factory.connect( + beaconProxyFactory, + l2Signer + ).cloneableProxyHash() + await ( + await l1TokenBridgeCreator.initTokenBridge( + l1Router, + l1StandardGateway, + l1CustomGateway, + await l1Signer.getAddress(), + inboxAddress, + l2Router, + l2StandardGateway, + l2CustomGateway, + cloneableProxyHash, + beaconProxyFactory + ) + ).wait() + + // init L2 side + await ( + await l2TokenBridgeFactory.initTokenBridge( + l1Router, + l1StandardGateway, + l1CustomGateway + ) + ).wait() + + return { + l1Router, + l1StandardGateway, + l1CustomGateway, + l1ProxyAdmin, + l2Router, + l2StandardGateway, + l2CustomGateway, + beaconProxyFactory, + l2ProxyAdmin, + } +} + +const deployTokenBridgeFactory = async (l1Signer: Signer) => { + /// deploy factory + console.log('Deploy L1TokenBridgeCreator') + + const l1TokenBridgeCreator = await new L1TokenBridgeCreator__factory( + l1Signer + ).deploy() + await l1TokenBridgeCreator.deployed() + console.log('l1TokenBridgeCreator', l1TokenBridgeCreator.address) + + /// deploy logic contracts + console.log('Create and set logic contracts') + + const routerTemplate = await new L1GatewayRouter__factory(l1Signer).deploy() + await routerTemplate.deployed() + + const standardGatewayTemplate = await new L1ERC20Gateway__factory( + l1Signer + ).deploy() + await standardGatewayTemplate.deployed() + + const customGatewayTemplate = await new L1CustomGateway__factory( + l1Signer + ).deploy() + await customGatewayTemplate.deployed() + + await ( + await l1TokenBridgeCreator.setTemplates( + routerTemplate.address, + standardGatewayTemplate.address, + customGatewayTemplate.address + ) + ).wait() + + return l1TokenBridgeCreator +} + +const bridgeFundsToL2Deployer = async ( + l1Signer: Signer, + inboxAddress: string +) => { + console.log('fund L2 deployer') + + const depositAmount = ethers.utils.parseUnits('3', 'ether') + + // bridge it + const InboxAbi = ['function depositEth() public payable returns (uint256)'] + const Inbox = new Contract(inboxAddress, InboxAbi, l1Signer) + await (await Inbox.depositEth({ value: depositAmount })).wait() + await sleep(30 * 1000) +} + +export const getLocalNetworks = async ( + l1Url: string, + l2Url: string +): Promise<{ + l1Network: L1Network + l2Network: Omit +}> => { + const l1Provider = new JsonRpcProvider(l1Url) + const l2Provider = new JsonRpcProvider(l2Url) + let deploymentData: string + try { + deploymentData = execSync( + 'docker exec nitro_testnode_sequencer_1 cat /config/deployment.json' + ).toString() + } catch (e) { + deploymentData = execSync( + 'docker exec nitro-testnode-sequencer-1 cat /config/deployment.json' + ).toString() + } + const parsedDeploymentData = JSON.parse(deploymentData) as { + bridge: string + inbox: string + ['sequencer-inbox']: string + rollup: string + } + + const rollup = RollupAdminLogic__factory.connect( + parsedDeploymentData.rollup, + l1Provider + ) + const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() + + const bridge = Bridge__factory.connect( + parsedDeploymentData.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 = { + chainID: l2NetworkInfo.chainId, + confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), + ethBridge: { + bridge: parsedDeploymentData.bridge, + inbox: parsedDeploymentData.inbox, + outbox: outboxAddr, + rollup: parsedDeploymentData.rollup, + sequencerInbox: parsedDeploymentData['sequencer-inbox'], + }, + explorerUrl: '', + isArbitrum: true, + isCustom: true, + name: 'ArbLocal', + partnerChainID: l1NetworkInfo.chainId, + retryableLifetimeSeconds: 7 * 24 * 60 * 60, + nitroGenesisBlock: 0, + nitroGenesisL1Block: 0, + depositTimeout: 900000, + } + return { + l1Network, + l2Network, + } +} + +export const getSigner = (provider: JsonRpcProvider, key?: string) => { + if (!key && !provider) + throw new Error('Provide at least one of key or provider.') + if (key) return new Wallet(key).connect(provider) + else return provider.getSigner(0) +} + +export function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)) +} + +async function main() { + const config = { + arbUrl: 'http://localhost:8547', + ethUrl: 'http://localhost:8545', + } + + const l1Provider = new ethers.providers.JsonRpcProvider(config.ethUrl) + const l2Provider = new ethers.providers.JsonRpcProvider(config.arbUrl) + + const l1DeployerWallet = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + l1Provider + ) + const l2DeployerWallet = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + l2Provider + ) + + const { l1Network, l2Network } = await setupTokenBridge( + l1DeployerWallet, + l2DeployerWallet, + config.ethUrl, + config.arbUrl + ) + + const NETWORK_FILE = 'network.json' + fs.writeFileSync( + NETWORK_FILE, + JSON.stringify({ l1Network, l2Network }, null, 2) + ) + console.log(NETWORK_FILE + ' updated') +} + +main().then(() => console.log('Done.')) From 34e6fe21e28603c9d3ae6a3e43ba1b272897834c Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 29 Jun 2023 12:22:47 +0200 Subject: [PATCH 081/163] Deploy and init L2 token bridge contracts in the same TX --- .../arbitrum/L2TokenBridgeFactory.sol | 38 +++++++------------ .../tokenBridgeDeployerViaFactories.ts | 13 +------ test-e2e/tokenBridgeDeploymentTest.ts | 2 +- 3 files changed, 17 insertions(+), 36 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol index 11429c8583..405a6dab0c 100644 --- a/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol @@ -10,12 +10,6 @@ import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract L2TokenBridgeFactory { - L2GatewayRouter public router; - L2ERC20Gateway public standardGateway; - L2CustomGateway public customGateway; - UpgradeableBeacon public beacon; - BeaconProxyFactory public beaconProxyFactory; - event OrbitL2TokenBridgeCreated( address router, address standardGateway, @@ -24,23 +18,30 @@ contract L2TokenBridgeFactory { address proxyAdmin ); - constructor() { + constructor(address l1Router, address l1StandardGateway, address l1CustomGateway) { address proxyAdmin = address(new ProxyAdmin()); // create router/gateways - router = L2GatewayRouter(_deployBehindProxy(address(new L2GatewayRouter()), proxyAdmin)); - standardGateway = L2ERC20Gateway( + L2GatewayRouter router = L2GatewayRouter( + _deployBehindProxy(address(new L2GatewayRouter()), proxyAdmin) + ); + L2ERC20Gateway standardGateway = L2ERC20Gateway( _deployBehindProxy(address(new L2ERC20Gateway()), proxyAdmin) ); - customGateway = L2CustomGateway( + L2CustomGateway customGateway = L2CustomGateway( _deployBehindProxy(address(new L2CustomGateway()), proxyAdmin) ); - // create and init beacon + // create beacon StandardArbERC20 standardArbERC20 = new StandardArbERC20(); - beacon = new UpgradeableBeacon(address(standardArbERC20)); - beaconProxyFactory = new BeaconProxyFactory(); + UpgradeableBeacon beacon = new UpgradeableBeacon(address(standardArbERC20)); + BeaconProxyFactory beaconProxyFactory = new BeaconProxyFactory(); + + // init contracts + router.initialize(l1Router, address(standardGateway)); beaconProxyFactory.initialize(address(beacon)); + standardGateway.initialize(l1StandardGateway, address(router), address(beaconProxyFactory)); + customGateway.initialize(l1CustomGateway, address(router)); emit OrbitL2TokenBridgeCreated( address(router), @@ -51,17 +52,6 @@ contract L2TokenBridgeFactory { ); } - function initTokenBridge( - address l1Router, - address l1StandardGateway, - address l1CustomGateway - ) external { - //// init router/gateways - router.initialize(l1Router, address(standardGateway)); - standardGateway.initialize(l1StandardGateway, address(router), address(beaconProxyFactory)); - customGateway.initialize(l1CustomGateway, address(router)); - } - function _deployBehindProxy(address logic, address proxyAdmin) internal returns (address) { return address(new TransparentUpgradeableProxy(logic, proxyAdmin, bytes(""))); } diff --git a/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts b/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts index 79f15f7608..54bb87d0e7 100644 --- a/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts +++ b/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts @@ -97,10 +97,10 @@ export const deployTokenBridgeAndInit = async ( proxyAdmin: l1ProxyAdmin, } = parsedLog[0].args - // deploy L2 side + // deploy+init L2 side const l2TokenBridgeFactory = await new L2TokenBridgeFactory__factory( l2Signer - ).deploy() + ).deploy(l1Router, l1StandardGateway, l1CustomGateway) await l2TokenBridgeFactory.deployed() const l2Receipt = await l2Signer.provider!.getTransactionReceipt( l2TokenBridgeFactory.deployTransaction.hash @@ -139,15 +139,6 @@ export const deployTokenBridgeAndInit = async ( ) ).wait() - // init L2 side - await ( - await l2TokenBridgeFactory.initTokenBridge( - l1Router, - l1StandardGateway, - l1CustomGateway - ) - ).wait() - return { l1Router, l1StandardGateway, diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index bcfd782e16..ceae4426d0 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -44,7 +44,7 @@ describe('tokenBridge', () => { // configure token bridge before(async function () {}) - it('should have deployed token bridge contracts', async function () { + it('should have deployed and initialized token bridge contracts', async function () { const { l1Network, l1Provider, l2Network, l2Provider } = await getProvidersAndSetupNetworks({ l1Url: config.ethUrl, From 033c2338a19327948d90547fbbf5b72d34d3b5a9 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 3 Jul 2023 12:18:34 +0200 Subject: [PATCH 082/163] Add plugin for checking contract sizes --- .../ethereum/L1TokenBridgeCreator.sol | 1 + hardhat.config.ts | 1 + package.json | 1 + yarn.lock | 28 +++++++++++++++++++ 4 files changed, 31 insertions(+) diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol index d3f716823d..10415160e3 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import { L1GatewayRouter } from "./gateway/L1GatewayRouter.sol"; diff --git a/hardhat.config.ts b/hardhat.config.ts index 3e494db759..e641a55748 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -6,6 +6,7 @@ import 'solidity-coverage' import 'hardhat-gas-reporter' import '@nomiclabs/hardhat-etherscan' import 'hardhat-deploy' +import 'hardhat-contract-sizer' import { task } from 'hardhat/config' import '@nomiclabs/hardhat-ethers' diff --git a/package.json b/package.json index 510aa8df86..f4f3cf1d51 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "ethereum-waffle": "^3.2.0", "ethers": "^5.4.5", "hardhat": "2.9.9", + "hardhat-contract-sizer": "^2.10.0", "hardhat-deploy": "^0.9.1", "hardhat-gas-reporter": "^1.0.4", "prettier": "^2.3.2", diff --git a/yarn.lock b/yarn.lock index ecc70a5ed3..4d097c1f56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -56,6 +56,11 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -2951,6 +2956,15 @@ cli-table3@^0.5.0: optionalDependencies: colors "^1.1.2" +cli-table3@^0.6.0: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -5454,6 +5468,15 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" +hardhat-contract-sizer@^2.10.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/hardhat-contract-sizer/-/hardhat-contract-sizer-2.10.0.tgz#72646f43bfe50e9a5702c9720c9bc3e77d93a2c9" + integrity sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA== + dependencies: + chalk "^4.0.0" + cli-table3 "^0.6.0" + strip-ansi "^6.0.0" + hardhat-deploy@^0.9.1: version "0.9.29" resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.9.29.tgz#b1177d4f3077f335ad3f50c55825d9417ec75968" @@ -9267,6 +9290,11 @@ solidity-coverage@v0.7.17: shelljs "^0.8.3" web3-utils "^1.3.0" +solmate@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/solmate/-/solmate-6.1.0.tgz#b85aaa8c2b34afe9c6d6d5a015c369267c576313" + integrity sha512-gxG4YU5nnAQ+Ac23R44GS3Xo3+X0+8XCe4/P1KvVobL5ERBzQBG/xMv7NSvVo/pkHSYGufgUAPjiueYxujKJAA== + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" From 26d02bb4255bfcc202565badfd5e0274d48d1c45 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 3 Jul 2023 12:48:47 +0200 Subject: [PATCH 083/163] Add 1st phase of atomic token bridge cross-chain deployer --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 82 ++++ .../ethereum/L1AtomicTokenBridgeCreator.sol | 170 +++++++ package.json | 6 +- .../atomicTokenBridgeDeployer.ts | 414 ++++++++++++++++++ 4 files changed, 670 insertions(+), 2 deletions(-) create mode 100644 contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol create mode 100644 contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol create mode 100644 scripts/local-deployment/atomicTokenBridgeDeployer.ts diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol new file mode 100644 index 0000000000..236ea51daf --- /dev/null +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +import { L2GatewayRouter } from "./gateway/L2GatewayRouter.sol"; +import { L2ERC20Gateway } from "./gateway/L2ERC20Gateway.sol"; +import { L2CustomGateway } from "./gateway/L2CustomGateway.sol"; +import { StandardArbERC20 } from "./StandardArbERC20.sol"; +import { BeaconProxyFactory } from "../libraries/ClonableBeaconProxy.sol"; +import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { CREATE3 } from "solmate/src/utils/CREATE3.sol"; + +contract L2AtomicTokenBridgeFactory { + event OrbitL2TokenBridgeCreated(address factory); + + address public proxyAdmin; + L2GatewayRouter public router; + + function deployRouter( + bytes memory creationCode, + address l1Router, + address standardGateway + ) external { + proxyAdmin = address(new ProxyAdmin()); + + address routerLogicAddress = CREATE3.deploy( + keccak256(bytes("OrbitL2GatewayRouter")), + creationCode, + 0 + ); + + // create proxy + router = L2GatewayRouter( + address(new TransparentUpgradeableProxy(routerLogicAddress, proxyAdmin, bytes(""))) + ); + + // init proxy + router.initialize(l1Router, address(standardGateway)); + } + + function deployStandardGateway(bytes memory creationCode, address l1StandardGateway) external { + address standardGatewayLogicAddress = CREATE3.deploy( + keccak256(bytes("OrbitL2StandardGateway")), + creationCode, + 0 + ); + + // create proxy + L2ERC20Gateway standardGateway = L2ERC20Gateway( + address( + new TransparentUpgradeableProxy(standardGatewayLogicAddress, proxyAdmin, bytes("")) + ) + ); + + // create beacon + StandardArbERC20 standardArbERC20 = new StandardArbERC20(); + UpgradeableBeacon beacon = new UpgradeableBeacon(address(standardArbERC20)); + BeaconProxyFactory beaconProxyFactory = new BeaconProxyFactory(); + + // init contracts + beaconProxyFactory.initialize(address(beacon)); + standardGateway.initialize(l1StandardGateway, address(router), address(beaconProxyFactory)); + } + + function deployCustomGateway(bytes memory creationCode, address l1CustomGateway) external { + address customGatewayLogicAddress = CREATE3.deploy( + keccak256(bytes("OrbitL2CustomGateway")), + creationCode, + 0 + ); + + // create proxy + L2CustomGateway customGateway = L2CustomGateway( + address( + new TransparentUpgradeableProxy(customGatewayLogicAddress, proxyAdmin, bytes("")) + ) + ); + + customGateway.initialize(l1CustomGateway, address(router)); + } +} diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol new file mode 100644 index 0000000000..75e145ee70 --- /dev/null +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +import { L1GatewayRouter } from "./gateway/L1GatewayRouter.sol"; +import { L1ERC20Gateway } from "./gateway/L1ERC20Gateway.sol"; +import { L1CustomGateway } from "./gateway/L1CustomGateway.sol"; +import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; + +import { IInbox } from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; + +contract L1AtomicTokenBridgeCreator is Ownable { + event OrbitTokenBridgeCreated( + address router, + address standardGateway, + address customGateway, + address proxyAdmin + ); + event OrbitTokenBridgeTemplatesUpdated(); + + L1GatewayRouter public routerTemplate; + L1ERC20Gateway public standardGatewayTemplate; + L1CustomGateway public customGatewayTemplate; + + function setTemplates( + L1GatewayRouter _router, + L1ERC20Gateway _standardGateway, + L1CustomGateway _customGateway + ) external onlyOwner { + routerTemplate = _router; + standardGatewayTemplate = _standardGateway; + customGatewayTemplate = _customGateway; + emit OrbitTokenBridgeTemplatesUpdated(); + } + + function createTokenBridge( + address l2FactoryAddressOnL1, + address inbox, + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 gasPriceBid + ) external payable { + address proxyAdmin = address(new ProxyAdmin()); + + L1GatewayRouter router = L1GatewayRouter( + address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes(""))) + ); + L1ERC20Gateway standardGateway = L1ERC20Gateway( + address( + new TransparentUpgradeableProxy( + address(standardGatewayTemplate), + proxyAdmin, + bytes("") + ) + ) + ); + L1CustomGateway customGateway = L1CustomGateway( + address( + new TransparentUpgradeableProxy( + address(customGatewayTemplate), + proxyAdmin, + bytes("") + ) + ) + ); + + emit OrbitTokenBridgeCreated( + address(router), + address(standardGateway), + address(customGateway), + proxyAdmin + ); + + _deployL2Factory(l2FactoryAddressOnL1, inbox, maxSubmissionCost, maxGas, gasPriceBid); + + // _deployL2TokenBridgeViaRetryable( + // l2TokenBridgeFactoryViaRetryables, + // inbox, + // address(router), + // address(standardGateway), + // address(customGateway), + // maxSubmissionCost, + // maxGas, + // gasPriceBid + // ); + + //// init contracts + // { + // /// dependencies - l2Router, l2StandardGateway, l2CustomGateway, cloneableProxyHash, l2BeaconProxyFactory, owner, inbox + // router.initialize(address(1), address(standardGateway), address(0), address(1), inbox); + // standardGateway.initialize(address(1), address(router), inbox, "abc", address(1)); + // customGateway.initialize(address(1), address(router), inbox, address(1)); + // } + } + + function _deployL2Factory( + address l2FactoryAddressOnL1, + address inbox, + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 gasPriceBid + ) internal returns (uint256) { + // encode L2 factory bytecode + bytes memory deploymentData = creationCodeFor(l2FactoryAddressOnL1.code); + + uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: msg.value }( + address(0), + 0, + maxSubmissionCost, + msg.sender, + msg.sender, + maxGas, + gasPriceBid, + deploymentData + ); + + return ticketID; + } + + // function _deployL2TokenBridgeViaRetryable( + // address l2TokenBridgeFactoryViaRetryables, + // address inbox, + // address l1Router, + // address l1StandardGateway, + // address l1CustomGateway, + // uint256 maxSubmissionCost, + // uint256 maxGas, + // uint256 gasPriceBid + // ) internal returns (uint256) { + // // encode L2 factory bytecode + encoded constructor args + // bytes memory bytecode = l2TokenBridgeFactoryViaRetryables.code; + // bytes memory args = abi.encodePacked(l1Router, l1StandardGateway, l1CustomGateway); + // bytes memory deploymentData = abi.encodePacked(bytecode, args); + + // uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: msg.value }( + // address(0), + // 0, + // maxSubmissionCost, + // msg.sender, + // msg.sender, + // maxGas, + // gasPriceBid, + // deploymentData + // ); + + // return ticketID; + // } + + /** + * @notice Generate a creation code that results on a contract with `_code` as bytecode + * @param _code The returning value of the resulting `creationCode` + * @return creationCode (constructor) for new contract + */ + function creationCodeFor(bytes memory _code) internal pure returns (bytes memory) { + /* + 0x00 0x63 0x63XXXXXX PUSH4 _code.length size + 0x01 0x80 0x80 DUP1 size size + 0x02 0x60 0x600e PUSH1 14 14 size size + 0x03 0x60 0x6000 PUSH1 00 0 14 size size + 0x04 0x39 0x39 CODECOPY size + 0x05 0x60 0x6000 PUSH1 00 0 size + 0x06 0xf3 0xf3 RETURN + + */ + + return + abi.encodePacked(hex"63", uint32(_code.length), hex"80_60_0E_60_00_39_60_00_F3", _code); + } +} diff --git a/package.json b/package.json index f4f3cf1d51..d9ceafd58e 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "test:l2": "hardhat test test/*.l2.ts", "test:storage": "./scripts/storage_layout_test.bash", "test:deploy:tokenbridge": "ts-node ./scripts/local-deployment/tokenBridgeDeployer.ts", - "test:deploy:tokenbridgeViaFactories": "ts-node ./scripts/local-deployment/tokenBridgeDeployerViaFactories.ts", + "test:deploy:tokenbridge:factories": "ts-node ./scripts/local-deployment/factoryTokenBridgeDeployer.ts", + "test:deploy:tokenbridge:atomic": "ts-node ./scripts/local-deployment/atomicTokenBridgeDeployer.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", @@ -36,7 +37,8 @@ "@arbitrum/nitro-contracts": "^1.0.0-beta.8", "@arbitrum/sdk": "^3.1.5", "@openzeppelin/contracts": "4.8.3", - "@openzeppelin/contracts-upgradeable": "4.8.3" + "@openzeppelin/contracts-upgradeable": "4.8.3", + "solmate": "^6.1.0" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.1", diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts new file mode 100644 index 0000000000..90e77a7f4f --- /dev/null +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -0,0 +1,414 @@ +import { Contract, Signer, Wallet, ethers } from 'ethers' +import { + L1CustomGateway__factory, + L1ERC20Gateway__factory, + L1GatewayRouter__factory, + L1AtomicTokenBridgeCreator__factory, + L2AtomicTokenBridgeFactory__factory, +} from '../../build/types' +import { JsonRpcProvider } from '@ethersproject/providers' +import { + L1Network, + L1ToL2MessageStatus, + L1TransactionReceipt, + L2Network, + addCustomNetwork, +} from '@arbitrum/sdk' +import { execSync } from 'child_process' +import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' +import * as fs from 'fs' +import { exit } from 'process' + +export const setupTokenBridge = async ( + l1Deployer: Signer, + l2Deployer: Signer, + l1Url: string, + l2Url: string +) => { + const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( + l1Url, + l2Url + ) + + addCustomNetwork({ + customL1Network: l1Network, + customL2Network: { + ...coreL2Network, + tokenBridge: { + l1CustomGateway: '', + l1ERC20Gateway: '', + l1GatewayRouter: '', + l1MultiCall: '', + l1ProxyAdmin: '', + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: '', + l2ERC20Gateway: '', + l2GatewayRouter: '', + l2Multicall: '', + l2ProxyAdmin: '', + l2Weth: '', + l2WethGateway: '', + }, + }, + }) + + const deployedContracts = await deployTokenBridgeAndInit( + l1Deployer, + l2Deployer, + coreL2Network.ethBridge.inbox + ) + + const l2Network: L2Network = { + ...coreL2Network, + tokenBridge: { + l1CustomGateway: deployedContracts.l1CustomGateway, + l1ERC20Gateway: deployedContracts.l1StandardGateway, + l1GatewayRouter: deployedContracts.l1Router, + l1MultiCall: '', + l1ProxyAdmin: deployedContracts.l1ProxyAdmin, + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: deployedContracts.l2CustomGateway, + l2ERC20Gateway: deployedContracts.l2StandardGateway, + l2GatewayRouter: deployedContracts.l2Router, + l2Multicall: '', + l2ProxyAdmin: deployedContracts.l2ProxyAdmin, + l2Weth: '', + l2WethGateway: '', + }, + } + + // addCustomNetwork({ + // customL1Network: l1Network, + // customL2Network: l2Network, + // }) + + return { + l1Network, + l2Network, + } +} + +/** + * Deploy all the L1 and L2 contracts and do the initialization. + * + * @param l1Signer + * @param l2Signer + * @param inboxAddress + * @returns + */ +export const deployTokenBridgeAndInit = async ( + l1Signer: Signer, + l2Signer: Signer, + inboxAddress: string +) => { + // deploy L1 creator + const l1TokenBridgeCreator = await deployTokenBridgeFactory(l1Signer) + + // deploy L2 contracts as templates on L1 + const l2TokenBridgeFactoryOnL1 = await deployL2TemplatesOnL1(l1Signer) + + // create token bridge + const maxSubmissionCost = ethers.utils.parseEther('0.1') + const maxGas = 10000000 + const gasPriceBid = ethers.utils.parseUnits('0.5', 'gwei') + const value = gasPriceBid.mul(maxGas).add(maxSubmissionCost).mul(2) + const receipt = await ( + await l1TokenBridgeCreator.createTokenBridge( + l2TokenBridgeFactoryOnL1, + inboxAddress, + maxSubmissionCost, + maxGas, + gasPriceBid, + { value: value } + ) + ).wait() + console.log('createTokenBridge done') + + /// wait for retryable execution + const l1TxReceipt = new L1TransactionReceipt(receipt) + const messages = await l1TxReceipt.getL1ToL2Messages(l2Signer) + const message = messages[0] + console.log( + 'Waiting for the L2 execution of the transaction. This may take up to 10-15 minutes ⏰' + ) + const messageResult = await message.waitForStatus() + + if (messageResult.status !== L1ToL2MessageStatus.REDEEMED) { + console.error( + `L2 retryable ticket is failed with status ${ + L1ToL2MessageStatus[messageResult.status] + }` + ) + exit() + } + + const L2AtomicTokenBridgeFactory = messageResult.l2TxReceipt.contractAddress + console.log('L2AtomicTokenBridgeFactory', L2AtomicTokenBridgeFactory) + + // get L1 deployed contracts + const iface = l1TokenBridgeCreator.interface + const eventFragment = iface.getEvent('OrbitTokenBridgeCreated') + const parsedLog = receipt.logs + .filter( + (curr: any) => curr.topics[0] === iface.getEventTopic(eventFragment) + ) + .map((curr: any) => iface.parseLog(curr)) + const { + router: l1Router, + standardGateway: l1StandardGateway, + customGateway: l1CustomGateway, + proxyAdmin: l1ProxyAdmin, + } = parsedLog[0].args + + // deploy+init L2 side + // const l2TokenBridgeFactory = await new L2TokenBridgeFactory__factory( + // l2Signer + // ).deploy(l1Router, l1StandardGateway, l1CustomGateway) + // await l2TokenBridgeFactory.deployed() + // const l2Receipt = await l2Signer.provider!.getTransactionReceipt( + // l2TokenBridgeFactory.deployTransaction.hash + // ) + + // const l2Iface = l2TokenBridgeFactory.interface + // const l2Event = l2Iface.getEvent('OrbitL2TokenBridgeCreated') + // const parsedL2Log = l2Receipt.logs + // .filter((curr: any) => curr.topics[0] === l2Iface.getEventTopic(l2Event)) + // .map((curr: any) => l2Iface.parseLog(curr)) + // const { + // router: l2Router, + // standardGateway: l2StandardGateway, + // customGateway: l2CustomGateway, + // beaconProxyFactory, + // proxyAdmin: l2ProxyAdmin, + // } = parsedL2Log[0].args + + // init L1 side + // const cloneableProxyHash = await BeaconProxyFactory__factory.connect( + // beaconProxyFactory, + // l2Signer + // ).cloneableProxyHash() + // await ( + // await l1TokenBridgeCreator.initTokenBridge( + // l1Router, + // l1StandardGateway, + // l1CustomGateway, + // await l1Signer.getAddress(), + // inboxAddress, + // l2Router, + // l2StandardGateway, + // l2CustomGateway, + // cloneableProxyHash, + // beaconProxyFactory + // ) + // ).wait() + + const l2Router = ethers.constants.AddressZero + const l2StandardGateway = ethers.constants.AddressZero + const l2CustomGateway = ethers.constants.AddressZero + const beaconProxyFactory = ethers.constants.AddressZero + const l2ProxyAdmin = ethers.constants.AddressZero + + return { + l1Router, + l1StandardGateway, + l1CustomGateway, + l1ProxyAdmin, + l2Router, + l2StandardGateway, + l2CustomGateway, + beaconProxyFactory, + l2ProxyAdmin, + } +} + +const deployTokenBridgeFactory = async (l1Signer: Signer) => { + /// deploy factory + console.log('Deploy L1AtomicTokenBridgeCreator') + + const l1TokenBridgeCreator = await new L1AtomicTokenBridgeCreator__factory( + l1Signer + ).deploy() + await l1TokenBridgeCreator.deployed() + console.log('l1TokenBridgeCreator', l1TokenBridgeCreator.address) + + /// deploy logic contracts + console.log('Create and set logic contracts') + + const routerTemplate = await new L1GatewayRouter__factory(l1Signer).deploy() + await routerTemplate.deployed() + + const standardGatewayTemplate = await new L1ERC20Gateway__factory( + l1Signer + ).deploy() + await standardGatewayTemplate.deployed() + + const customGatewayTemplate = await new L1CustomGateway__factory( + l1Signer + ).deploy() + await customGatewayTemplate.deployed() + + await ( + await l1TokenBridgeCreator.setTemplates( + routerTemplate.address, + standardGatewayTemplate.address, + customGatewayTemplate.address + ) + ).wait() + + return l1TokenBridgeCreator +} + +const deployL2TemplatesOnL1 = async (l1Signer: Signer) => { + /// deploy factory + console.log('Deploy L2AtomicTokenBridgeFactory') + + const l2TokenBridgeFactoryOnL1 = + await new L2AtomicTokenBridgeFactory__factory(l1Signer).deploy() + await l2TokenBridgeFactoryOnL1.deployed() + console.log('l2TokenBridgeFactoryOnL1', l2TokenBridgeFactoryOnL1.address) + + return l2TokenBridgeFactoryOnL1.address +} + +const bridgeFundsToL2Deployer = async ( + l1Signer: Signer, + inboxAddress: string +) => { + console.log('fund L2 deployer') + + const depositAmount = ethers.utils.parseUnits('3', 'ether') + + // bridge it + const InboxAbi = ['function depositEth() public payable returns (uint256)'] + const Inbox = new Contract(inboxAddress, InboxAbi, l1Signer) + await (await Inbox.depositEth({ value: depositAmount })).wait() + await sleep(30 * 1000) +} + +export const getLocalNetworks = async ( + l1Url: string, + l2Url: string +): Promise<{ + l1Network: L1Network + l2Network: Omit +}> => { + const l1Provider = new JsonRpcProvider(l1Url) + const l2Provider = new JsonRpcProvider(l2Url) + let deploymentData: string + try { + deploymentData = execSync( + 'docker exec nitro_testnode_sequencer_1 cat /config/deployment.json' + ).toString() + } catch (e) { + deploymentData = execSync( + 'docker exec nitro-testnode-sequencer-1 cat /config/deployment.json' + ).toString() + } + const parsedDeploymentData = JSON.parse(deploymentData) as { + bridge: string + inbox: string + ['sequencer-inbox']: string + rollup: string + } + + const rollup = RollupAdminLogic__factory.connect( + parsedDeploymentData.rollup, + l1Provider + ) + const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() + + const bridge = Bridge__factory.connect( + parsedDeploymentData.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 = { + chainID: l2NetworkInfo.chainId, + confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), + ethBridge: { + bridge: parsedDeploymentData.bridge, + inbox: parsedDeploymentData.inbox, + outbox: outboxAddr, + rollup: parsedDeploymentData.rollup, + sequencerInbox: parsedDeploymentData['sequencer-inbox'], + }, + explorerUrl: '', + isArbitrum: true, + isCustom: true, + name: 'ArbLocal', + partnerChainID: l1NetworkInfo.chainId, + retryableLifetimeSeconds: 7 * 24 * 60 * 60, + nitroGenesisBlock: 0, + nitroGenesisL1Block: 0, + depositTimeout: 900000, + } + return { + l1Network, + l2Network, + } +} + +export const getSigner = (provider: JsonRpcProvider, key?: string) => { + if (!key && !provider) + throw new Error('Provide at least one of key or provider.') + if (key) return new Wallet(key).connect(provider) + else return provider.getSigner(0) +} + +export function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)) +} + +async function main() { + const config = { + arbUrl: 'http://localhost:8547', + ethUrl: 'http://localhost:8545', + } + + const l1Provider = new ethers.providers.JsonRpcProvider(config.ethUrl) + const l2Provider = new ethers.providers.JsonRpcProvider(config.arbUrl) + + const l1DeployerWallet = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + l1Provider + ) + const l2DeployerWallet = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + l2Provider + ) + + const { l1Network, l2Network } = await setupTokenBridge( + l1DeployerWallet, + l2DeployerWallet, + config.ethUrl, + config.arbUrl + ) + + const NETWORK_FILE = 'network.json' + fs.writeFileSync( + NETWORK_FILE, + JSON.stringify({ l1Network, l2Network }, null, 2) + ) + console.log(NETWORK_FILE + ' updated') +} + +main().then(() => console.log('Done.')) From 80075afdf115a6a36751e99f11d5e582e8457752 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 3 Jul 2023 17:27:34 +0200 Subject: [PATCH 084/163] Deploy L2 router using retryable --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 4 +- .../ethereum/L1AtomicTokenBridgeCreator.sol | 121 +++++++++++++----- .../atomicTokenBridgeDeployer.ts | 97 ++++++++------ 3 files changed, 155 insertions(+), 67 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 236ea51daf..578db72ee2 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -12,7 +12,7 @@ import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/trans import { CREATE3 } from "solmate/src/utils/CREATE3.sol"; contract L2AtomicTokenBridgeFactory { - event OrbitL2TokenBridgeCreated(address factory); + event OrbitL2TokenBridgeCreated(address router); address public proxyAdmin; L2GatewayRouter public router; @@ -37,6 +37,8 @@ contract L2AtomicTokenBridgeFactory { // init proxy router.initialize(l1Router, address(standardGateway)); + + emit OrbitL2TokenBridgeCreated(address(router)); } function deployStandardGateway(bytes memory creationCode, address l1StandardGateway) external { diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 75e145ee70..e09038fbf5 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -6,9 +6,10 @@ import { L1ERC20Gateway } from "./gateway/L1ERC20Gateway.sol"; import { L1CustomGateway } from "./gateway/L1CustomGateway.sol"; import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { L2AtomicTokenBridgeFactory } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; - import { IInbox } from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; +import { AddressAliasHelper } from "../libraries/AddressAliasHelper.sol"; contract L1AtomicTokenBridgeCreator is Ownable { event OrbitTokenBridgeCreated( @@ -36,6 +37,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { function createTokenBridge( address l2FactoryAddressOnL1, + address l2RouterAddressOnL1, address inbox, uint256 maxSubmissionCost, uint256 maxGas, @@ -73,6 +75,14 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); _deployL2Factory(l2FactoryAddressOnL1, inbox, maxSubmissionCost, maxGas, gasPriceBid); + _deployL2Router( + l2RouterAddressOnL1, + address(router), + inbox, + maxSubmissionCost, + maxGas, + gasPriceBid + ); // _deployL2TokenBridgeViaRetryable( // l2TokenBridgeFactoryViaRetryables, @@ -104,7 +114,8 @@ contract L1AtomicTokenBridgeCreator is Ownable { // encode L2 factory bytecode bytes memory deploymentData = creationCodeFor(l2FactoryAddressOnL1.code); - uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: msg.value }( + uint256 value = maxSubmissionCost + maxGas * gasPriceBid; + uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( address(0), 0, maxSubmissionCost, @@ -118,34 +129,43 @@ contract L1AtomicTokenBridgeCreator is Ownable { return ticketID; } - // function _deployL2TokenBridgeViaRetryable( - // address l2TokenBridgeFactoryViaRetryables, - // address inbox, - // address l1Router, - // address l1StandardGateway, - // address l1CustomGateway, - // uint256 maxSubmissionCost, - // uint256 maxGas, - // uint256 gasPriceBid - // ) internal returns (uint256) { - // // encode L2 factory bytecode + encoded constructor args - // bytes memory bytecode = l2TokenBridgeFactoryViaRetryables.code; - // bytes memory args = abi.encodePacked(l1Router, l1StandardGateway, l1CustomGateway); - // bytes memory deploymentData = abi.encodePacked(bytecode, args); - - // uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: msg.value }( - // address(0), - // 0, - // maxSubmissionCost, - // msg.sender, - // msg.sender, - // maxGas, - // gasPriceBid, - // deploymentData - // ); - - // return ticketID; - // } + function _deployL2Router( + address l2RouterAddressOnL1, + address l1Router, + address inbox, + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 gasPriceBid + ) internal returns (uint256) { + // encode L2 factory bytecode + bytes memory creationCode = creationCodeFor(l2RouterAddressOnL1.code); + + // address l2StandardGateway = address(1337); + + bytes memory data = abi.encodeWithSelector( + L2AtomicTokenBridgeFactory.deployRouter.selector, + creationCode, + l1Router, + address(1337) + ); + + uint256 value = maxSubmissionCost + maxGas * gasPriceBid; + address l2FactoryAddress = calculateAddress( + AddressAliasHelper.applyL1ToL2Alias(address(this)), + 0 + ); + uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( + l2FactoryAddress, + 0, + maxSubmissionCost, + msg.sender, + msg.sender, + maxGas, + gasPriceBid, + data + ); + return ticketID; + } /** * @notice Generate a creation code that results on a contract with `_code` as bytecode @@ -167,4 +187,45 @@ contract L1AtomicTokenBridgeCreator is Ownable { return abi.encodePacked(hex"63", uint32(_code.length), hex"80_60_0E_60_00_39_60_00_F3", _code); } + + function calculateAddress(address _origin, uint _nonce) public pure returns (address) { + bytes memory data; + if (_nonce == 0x00) + data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, bytes1(0x80)); + else if (_nonce <= 0x7f) + data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, uint8(_nonce)); + else if (_nonce <= 0xff) + data = abi.encodePacked( + bytes1(0xd7), + bytes1(0x94), + _origin, + bytes1(0x81), + uint8(_nonce) + ); + else if (_nonce <= 0xffff) + data = abi.encodePacked( + bytes1(0xd8), + bytes1(0x94), + _origin, + bytes1(0x82), + uint16(_nonce) + ); + else if (_nonce <= 0xffffff) + data = abi.encodePacked( + bytes1(0xd9), + bytes1(0x94), + _origin, + bytes1(0x83), + uint24(_nonce) + ); + else + data = abi.encodePacked( + bytes1(0xda), + bytes1(0x94), + _origin, + bytes1(0x84), + uint32(_nonce) + ); + return address(uint160(uint256(keccak256(data)))); + } } diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 90e77a7f4f..2620f5cdc2 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -5,6 +5,7 @@ import { L1GatewayRouter__factory, L1AtomicTokenBridgeCreator__factory, L2AtomicTokenBridgeFactory__factory, + L2GatewayRouter__factory, } from '../../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { @@ -14,11 +15,11 @@ import { L2Network, addCustomNetwork, } from '@arbitrum/sdk' -import { execSync } from 'child_process' import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' import * as fs from 'fs' import { exit } from 'process' +import { execSync } from 'child_process' export const setupTokenBridge = async ( l1Deployer: Signer, @@ -110,16 +111,18 @@ export const deployTokenBridgeAndInit = async ( const l1TokenBridgeCreator = await deployTokenBridgeFactory(l1Signer) // deploy L2 contracts as templates on L1 - const l2TokenBridgeFactoryOnL1 = await deployL2TemplatesOnL1(l1Signer) + const { l2TokenBridgeFactoryOnL1, l2GatewayRouterOnL1 } = + await deployL2TemplatesOnL1(l1Signer) // create token bridge const maxSubmissionCost = ethers.utils.parseEther('0.1') const maxGas = 10000000 const gasPriceBid = ethers.utils.parseUnits('0.5', 'gwei') - const value = gasPriceBid.mul(maxGas).add(maxSubmissionCost).mul(2) + const value = gasPriceBid.mul(maxGas).add(maxSubmissionCost).mul(5) const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( - l2TokenBridgeFactoryOnL1, + l2TokenBridgeFactoryOnL1.address, + l2GatewayRouterOnL1.address, inboxAddress, maxSubmissionCost, maxGas, @@ -132,12 +135,9 @@ export const deployTokenBridgeAndInit = async ( /// wait for retryable execution const l1TxReceipt = new L1TransactionReceipt(receipt) const messages = await l1TxReceipt.getL1ToL2Messages(l2Signer) - const message = messages[0] - console.log( - 'Waiting for the L2 execution of the transaction. This may take up to 10-15 minutes ⏰' - ) - const messageResult = await message.waitForStatus() + // 1st msg - deploy factory + const messageResult = await messages[0].waitForStatus() if (messageResult.status !== L1ToL2MessageStatus.REDEEMED) { console.error( `L2 retryable ticket is failed with status ${ @@ -147,23 +147,39 @@ export const deployTokenBridgeAndInit = async ( exit() } - const L2AtomicTokenBridgeFactory = messageResult.l2TxReceipt.contractAddress - console.log('L2AtomicTokenBridgeFactory', L2AtomicTokenBridgeFactory) + const l2AtomicTokenBridgeFactory = + L2AtomicTokenBridgeFactory__factory.connect( + messageResult.l2TxReceipt.contractAddress, + l2Signer + ) + console.log('L2AtomicTokenBridgeFactory', l2AtomicTokenBridgeFactory.address) - // get L1 deployed contracts - const iface = l1TokenBridgeCreator.interface - const eventFragment = iface.getEvent('OrbitTokenBridgeCreated') - const parsedLog = receipt.logs - .filter( - (curr: any) => curr.topics[0] === iface.getEventTopic(eventFragment) + // 2nd msg - deploy router + const messageRouterResult = await messages[1].waitForStatus() + if (messageRouterResult.status !== L1ToL2MessageStatus.REDEEMED) { + console.error( + `L2 retryable ticket is failed with status ${ + L1ToL2MessageStatus[messageRouterResult.status] + }` ) - .map((curr: any) => iface.parseLog(curr)) + exit() + } + + /// get L1 deployed contracts const { router: l1Router, standardGateway: l1StandardGateway, customGateway: l1CustomGateway, proxyAdmin: l1ProxyAdmin, - } = parsedLog[0].args + } = getParsedLogs( + receipt.logs, + l1TokenBridgeCreator.interface, + 'OrbitTokenBridgeCreated' + )[0].args + + /// get L2 router + const l2Router = await l2AtomicTokenBridgeFactory.router() + console.log('l2Router', l2Router) // deploy+init L2 side // const l2TokenBridgeFactory = await new L2TokenBridgeFactory__factory( @@ -207,7 +223,7 @@ export const deployTokenBridgeAndInit = async ( // ) // ).wait() - const l2Router = ethers.constants.AddressZero + // const l2Router = ethers.constants.AddressZero const l2StandardGateway = ethers.constants.AddressZero const l2CustomGateway = ethers.constants.AddressZero const beaconProxyFactory = ethers.constants.AddressZero @@ -226,6 +242,20 @@ export const deployTokenBridgeAndInit = async ( } } +const getParsedLogs = ( + logs: ethers.providers.Log[], + iface: ethers.utils.Interface, + eventName: string +) => { + const eventFragment = iface.getEvent(eventName) + const parsedLogs = logs + .filter( + (curr: any) => curr.topics[0] === iface.getEventTopic(eventFragment) + ) + .map((curr: any) => iface.parseLog(curr)) + return parsedLogs +} + const deployTokenBridgeFactory = async (l1Signer: Signer) => { /// deploy factory console.log('Deploy L1AtomicTokenBridgeCreator') @@ -266,28 +296,23 @@ const deployTokenBridgeFactory = async (l1Signer: Signer) => { const deployL2TemplatesOnL1 = async (l1Signer: Signer) => { /// deploy factory console.log('Deploy L2AtomicTokenBridgeFactory') - const l2TokenBridgeFactoryOnL1 = await new L2AtomicTokenBridgeFactory__factory(l1Signer).deploy() await l2TokenBridgeFactoryOnL1.deployed() console.log('l2TokenBridgeFactoryOnL1', l2TokenBridgeFactoryOnL1.address) - return l2TokenBridgeFactoryOnL1.address -} - -const bridgeFundsToL2Deployer = async ( - l1Signer: Signer, - inboxAddress: string -) => { - console.log('fund L2 deployer') - - const depositAmount = ethers.utils.parseUnits('3', 'ether') + /// deploy router + console.log('Deploy L2AtomicTokenBridgeFactory') + const l2GatewayRouterOnL1 = await new L2GatewayRouter__factory( + l1Signer + ).deploy() + await l2GatewayRouterOnL1.deployed() + console.log('l2GatewayRouteronL1', l2GatewayRouterOnL1.address) - // bridge it - const InboxAbi = ['function depositEth() public payable returns (uint256)'] - const Inbox = new Contract(inboxAddress, InboxAbi, l1Signer) - await (await Inbox.depositEth({ value: depositAmount })).wait() - await sleep(30 * 1000) + return { + l2TokenBridgeFactoryOnL1, + l2GatewayRouterOnL1, + } } export const getLocalNetworks = async ( From 95c14316368e5d01576e41a3dee3e3cb5de8ef07 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 3 Jul 2023 17:54:53 +0200 Subject: [PATCH 085/163] Deploy L2 standard gateway using retryable --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 3 +- .../ethereum/L1AtomicTokenBridgeCreator.sol | 45 +++++++++++ .../atomicTokenBridgeDeployer.ts | 81 ++++++++----------- 3 files changed, 82 insertions(+), 47 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 578db72ee2..d89885cc78 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -16,6 +16,7 @@ contract L2AtomicTokenBridgeFactory { address public proxyAdmin; L2GatewayRouter public router; + L2ERC20Gateway public standardGateway; function deployRouter( bytes memory creationCode, @@ -49,7 +50,7 @@ contract L2AtomicTokenBridgeFactory { ); // create proxy - L2ERC20Gateway standardGateway = L2ERC20Gateway( + standardGateway = L2ERC20Gateway( address( new TransparentUpgradeableProxy(standardGatewayLogicAddress, proxyAdmin, bytes("")) ) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index e09038fbf5..01cfe30ba6 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -38,6 +38,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { function createTokenBridge( address l2FactoryAddressOnL1, address l2RouterAddressOnL1, + address l2StandardGatewayAddressOnL1, address inbox, uint256 maxSubmissionCost, uint256 maxGas, @@ -83,6 +84,14 @@ contract L1AtomicTokenBridgeCreator is Ownable { maxGas, gasPriceBid ); + _deployL2StandardGateway( + l2StandardGatewayAddressOnL1, + address(standardGateway), + inbox, + maxSubmissionCost, + maxGas, + gasPriceBid + ); // _deployL2TokenBridgeViaRetryable( // l2TokenBridgeFactoryViaRetryables, @@ -167,6 +176,42 @@ contract L1AtomicTokenBridgeCreator is Ownable { return ticketID; } + function _deployL2StandardGateway( + address l2StandardGatewayAddressOnL1, + address l1StandardGateway, + address inbox, + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 gasPriceBid + ) internal returns (uint256) { + // encode L2 gateway bytecode + bytes memory creationCode = creationCodeFor(l2StandardGatewayAddressOnL1.code); + + bytes memory data = abi.encodeWithSelector( + L2AtomicTokenBridgeFactory.deployStandardGateway.selector, + creationCode, + l1StandardGateway, + address(1337) + ); + + uint256 value = maxSubmissionCost + maxGas * gasPriceBid; + address l2FactoryAddress = calculateAddress( + AddressAliasHelper.applyL1ToL2Alias(address(this)), + 0 + ); + uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( + l2FactoryAddress, + 0, + maxSubmissionCost, + msg.sender, + msg.sender, + maxGas, + gasPriceBid, + data + ); + return ticketID; + } + /** * @notice Generate a creation code that results on a contract with `_code` as bytecode * @param _code The returning value of the resulting `creationCode` diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 2620f5cdc2..8d2d68ff02 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -6,6 +6,7 @@ import { L1AtomicTokenBridgeCreator__factory, L2AtomicTokenBridgeFactory__factory, L2GatewayRouter__factory, + L2ERC20Gateway__factory, } from '../../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { @@ -111,8 +112,11 @@ export const deployTokenBridgeAndInit = async ( const l1TokenBridgeCreator = await deployTokenBridgeFactory(l1Signer) // deploy L2 contracts as templates on L1 - const { l2TokenBridgeFactoryOnL1, l2GatewayRouterOnL1 } = - await deployL2TemplatesOnL1(l1Signer) + const { + l2TokenBridgeFactoryOnL1, + l2GatewayRouterOnL1, + l2StandardGatewayAddressOnL1, + } = await deployL2TemplatesOnL1(l1Signer) // create token bridge const maxSubmissionCost = ethers.utils.parseEther('0.1') @@ -123,6 +127,7 @@ export const deployTokenBridgeAndInit = async ( await l1TokenBridgeCreator.createTokenBridge( l2TokenBridgeFactoryOnL1.address, l2GatewayRouterOnL1.address, + l2StandardGatewayAddressOnL1.address, inboxAddress, maxSubmissionCost, maxGas, @@ -165,6 +170,17 @@ export const deployTokenBridgeAndInit = async ( exit() } + // 3rd msg - deploy router + const messageStdGwResult = await messages[2].waitForStatus() + if (messageRouterResult.status !== L1ToL2MessageStatus.REDEEMED) { + console.error( + `L2 retryable ticket is failed with status ${ + L1ToL2MessageStatus[messageStdGwResult.status] + }` + ) + exit() + } + /// get L1 deployed contracts const { router: l1Router, @@ -181,50 +197,11 @@ export const deployTokenBridgeAndInit = async ( const l2Router = await l2AtomicTokenBridgeFactory.router() console.log('l2Router', l2Router) - // deploy+init L2 side - // const l2TokenBridgeFactory = await new L2TokenBridgeFactory__factory( - // l2Signer - // ).deploy(l1Router, l1StandardGateway, l1CustomGateway) - // await l2TokenBridgeFactory.deployed() - // const l2Receipt = await l2Signer.provider!.getTransactionReceipt( - // l2TokenBridgeFactory.deployTransaction.hash - // ) - - // const l2Iface = l2TokenBridgeFactory.interface - // const l2Event = l2Iface.getEvent('OrbitL2TokenBridgeCreated') - // const parsedL2Log = l2Receipt.logs - // .filter((curr: any) => curr.topics[0] === l2Iface.getEventTopic(l2Event)) - // .map((curr: any) => l2Iface.parseLog(curr)) - // const { - // router: l2Router, - // standardGateway: l2StandardGateway, - // customGateway: l2CustomGateway, - // beaconProxyFactory, - // proxyAdmin: l2ProxyAdmin, - // } = parsedL2Log[0].args - - // init L1 side - // const cloneableProxyHash = await BeaconProxyFactory__factory.connect( - // beaconProxyFactory, - // l2Signer - // ).cloneableProxyHash() - // await ( - // await l1TokenBridgeCreator.initTokenBridge( - // l1Router, - // l1StandardGateway, - // l1CustomGateway, - // await l1Signer.getAddress(), - // inboxAddress, - // l2Router, - // l2StandardGateway, - // l2CustomGateway, - // cloneableProxyHash, - // beaconProxyFactory - // ) - // ).wait() - - // const l2Router = ethers.constants.AddressZero - const l2StandardGateway = ethers.constants.AddressZero + /// get L2 standard gateway + const l2StandardGateway = await l2AtomicTokenBridgeFactory.standardGateway() + console.log('l2StandardGateway', l2StandardGateway) + + // placeholder const l2CustomGateway = ethers.constants.AddressZero const beaconProxyFactory = ethers.constants.AddressZero const l2ProxyAdmin = ethers.constants.AddressZero @@ -309,9 +286,21 @@ const deployL2TemplatesOnL1 = async (l1Signer: Signer) => { await l2GatewayRouterOnL1.deployed() console.log('l2GatewayRouteronL1', l2GatewayRouterOnL1.address) + /// deploy standard gateway + console.log('Deploy L2ERC20Gateway') + const l2StandardGatewayAddressOnL1 = await new L2ERC20Gateway__factory( + l1Signer + ).deploy() + await l2StandardGatewayAddressOnL1.deployed() + console.log( + 'l2StandardGatewayAddressOnL1', + l2StandardGatewayAddressOnL1.address + ) + return { l2TokenBridgeFactoryOnL1, l2GatewayRouterOnL1, + l2StandardGatewayAddressOnL1, } } From 5e2954f963f3ae165e6922f6ce2dd6aecf363b15 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 3 Jul 2023 19:26:46 +0200 Subject: [PATCH 086/163] Deploy L2 custom gateway via retryable --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 7 +-- .../ethereum/L1AtomicTokenBridgeCreator.sol | 58 ++++++++++++++----- .../atomicTokenBridgeDeployer.ts | 56 ++++++++++++------ 3 files changed, 85 insertions(+), 36 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index d89885cc78..50f568192d 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -12,11 +12,10 @@ import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/trans import { CREATE3 } from "solmate/src/utils/CREATE3.sol"; contract L2AtomicTokenBridgeFactory { - event OrbitL2TokenBridgeCreated(address router); - address public proxyAdmin; L2GatewayRouter public router; L2ERC20Gateway public standardGateway; + L2CustomGateway public customGateway; function deployRouter( bytes memory creationCode, @@ -38,8 +37,6 @@ contract L2AtomicTokenBridgeFactory { // init proxy router.initialize(l1Router, address(standardGateway)); - - emit OrbitL2TokenBridgeCreated(address(router)); } function deployStandardGateway(bytes memory creationCode, address l1StandardGateway) external { @@ -74,7 +71,7 @@ contract L2AtomicTokenBridgeFactory { ); // create proxy - L2CustomGateway customGateway = L2CustomGateway( + customGateway = L2CustomGateway( address( new TransparentUpgradeableProxy(customGatewayLogicAddress, proxyAdmin, bytes("")) ) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 01cfe30ba6..6c290f19a5 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -39,6 +39,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { address l2FactoryAddressOnL1, address l2RouterAddressOnL1, address l2StandardGatewayAddressOnL1, + address l2CustomGatewayAddressOnL1, address inbox, uint256 maxSubmissionCost, uint256 maxGas, @@ -92,17 +93,14 @@ contract L1AtomicTokenBridgeCreator is Ownable { maxGas, gasPriceBid ); - - // _deployL2TokenBridgeViaRetryable( - // l2TokenBridgeFactoryViaRetryables, - // inbox, - // address(router), - // address(standardGateway), - // address(customGateway), - // maxSubmissionCost, - // maxGas, - // gasPriceBid - // ); + _deployL2CustomGateway( + l2CustomGatewayAddressOnL1, + address(customGateway), + inbox, + maxSubmissionCost, + maxGas, + gasPriceBid + ); //// init contracts // { @@ -190,8 +188,42 @@ contract L1AtomicTokenBridgeCreator is Ownable { bytes memory data = abi.encodeWithSelector( L2AtomicTokenBridgeFactory.deployStandardGateway.selector, creationCode, - l1StandardGateway, - address(1337) + l1StandardGateway + ); + + uint256 value = maxSubmissionCost + maxGas * gasPriceBid; + address l2FactoryAddress = calculateAddress( + AddressAliasHelper.applyL1ToL2Alias(address(this)), + 0 + ); + uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( + l2FactoryAddress, + 0, + maxSubmissionCost, + msg.sender, + msg.sender, + maxGas, + gasPriceBid, + data + ); + return ticketID; + } + + function _deployL2CustomGateway( + address l2CustomGatewayAddressOnL1, + address l1CustomGateway, + address inbox, + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 gasPriceBid + ) internal returns (uint256) { + // encode L2 custom gateway bytecode + bytes memory creationCode = creationCodeFor(l2CustomGatewayAddressOnL1.code); + + bytes memory data = abi.encodeWithSelector( + L2AtomicTokenBridgeFactory.deployCustomGateway.selector, + creationCode, + l1CustomGateway ); uint256 value = maxSubmissionCost + maxGas * gasPriceBid; diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 8d2d68ff02..2d2f77d145 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -7,6 +7,7 @@ import { L2AtomicTokenBridgeFactory__factory, L2GatewayRouter__factory, L2ERC20Gateway__factory, + L2CustomGateway__factory, } from '../../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { @@ -116,6 +117,7 @@ export const deployTokenBridgeAndInit = async ( l2TokenBridgeFactoryOnL1, l2GatewayRouterOnL1, l2StandardGatewayAddressOnL1, + l2CustomGatewayAddressOnL1, } = await deployL2TemplatesOnL1(l1Signer) // create token bridge @@ -128,6 +130,7 @@ export const deployTokenBridgeAndInit = async ( l2TokenBridgeFactoryOnL1.address, l2GatewayRouterOnL1.address, l2StandardGatewayAddressOnL1.address, + l2CustomGatewayAddressOnL1.address, inboxAddress, maxSubmissionCost, maxGas, @@ -145,7 +148,7 @@ export const deployTokenBridgeAndInit = async ( const messageResult = await messages[0].waitForStatus() if (messageResult.status !== L1ToL2MessageStatus.REDEEMED) { console.error( - `L2 retryable ticket is failed with status ${ + `1 L2 retryable ticket is failed with status ${ L1ToL2MessageStatus[messageResult.status] }` ) @@ -163,24 +166,35 @@ export const deployTokenBridgeAndInit = async ( const messageRouterResult = await messages[1].waitForStatus() if (messageRouterResult.status !== L1ToL2MessageStatus.REDEEMED) { console.error( - `L2 retryable ticket is failed with status ${ + `2 L2 retryable ticket is failed with status ${ L1ToL2MessageStatus[messageRouterResult.status] }` ) exit() } - // 3rd msg - deploy router + // 3rd msg - deploy standard gw const messageStdGwResult = await messages[2].waitForStatus() if (messageRouterResult.status !== L1ToL2MessageStatus.REDEEMED) { console.error( - `L2 retryable ticket is failed with status ${ + `3 L2 retryable ticket is failed with status ${ L1ToL2MessageStatus[messageStdGwResult.status] }` ) exit() } + // 4th msg - deploy custom gw + const messageCustomGwResult = await messages[3].waitForStatus() + if (messageCustomGwResult.status !== L1ToL2MessageStatus.REDEEMED) { + console.error( + `4 L2 retryable ticket is failed with status ${ + L1ToL2MessageStatus[messageCustomGwResult.status] + }` + ) + exit() + } + /// get L1 deployed contracts const { router: l1Router, @@ -195,16 +209,20 @@ export const deployTokenBridgeAndInit = async ( /// get L2 router const l2Router = await l2AtomicTokenBridgeFactory.router() - console.log('l2Router', l2Router) /// get L2 standard gateway - const l2StandardGateway = await l2AtomicTokenBridgeFactory.standardGateway() - console.log('l2StandardGateway', l2StandardGateway) + const l2StandardGateway = L2ERC20Gateway__factory.connect( + await l2AtomicTokenBridgeFactory.standardGateway(), + l2Signer + ) + const beaconProxyFactory = await l2StandardGateway.beaconProxyFactory() - // placeholder - const l2CustomGateway = ethers.constants.AddressZero - const beaconProxyFactory = ethers.constants.AddressZero - const l2ProxyAdmin = ethers.constants.AddressZero + /// get L2 standard gateway + const l2CustomGateway = await l2AtomicTokenBridgeFactory.customGateway() + console.log('l2CustomGateway', l2CustomGateway) + + /// get L2 proxy admin + const l2ProxyAdmin = await l2AtomicTokenBridgeFactory.proxyAdmin() return { l1Router, @@ -212,7 +230,7 @@ export const deployTokenBridgeAndInit = async ( l1CustomGateway, l1ProxyAdmin, l2Router, - l2StandardGateway, + l2StandardGateway: l2StandardGateway.address, l2CustomGateway, beaconProxyFactory, l2ProxyAdmin, @@ -276,7 +294,6 @@ const deployL2TemplatesOnL1 = async (l1Signer: Signer) => { const l2TokenBridgeFactoryOnL1 = await new L2AtomicTokenBridgeFactory__factory(l1Signer).deploy() await l2TokenBridgeFactoryOnL1.deployed() - console.log('l2TokenBridgeFactoryOnL1', l2TokenBridgeFactoryOnL1.address) /// deploy router console.log('Deploy L2AtomicTokenBridgeFactory') @@ -284,7 +301,6 @@ const deployL2TemplatesOnL1 = async (l1Signer: Signer) => { l1Signer ).deploy() await l2GatewayRouterOnL1.deployed() - console.log('l2GatewayRouteronL1', l2GatewayRouterOnL1.address) /// deploy standard gateway console.log('Deploy L2ERC20Gateway') @@ -292,15 +308,19 @@ const deployL2TemplatesOnL1 = async (l1Signer: Signer) => { l1Signer ).deploy() await l2StandardGatewayAddressOnL1.deployed() - console.log( - 'l2StandardGatewayAddressOnL1', - l2StandardGatewayAddressOnL1.address - ) + + /// deploy custom gateway + console.log('Deploy L2CustomGateway') + const l2CustomGatewayAddressOnL1 = await new L2CustomGateway__factory( + l1Signer + ).deploy() + await l2CustomGatewayAddressOnL1.deployed() return { l2TokenBridgeFactoryOnL1, l2GatewayRouterOnL1, l2StandardGatewayAddressOnL1, + l2CustomGatewayAddressOnL1, } } From 82fa746ed3ab9985da92ba8b663f03d67e22c9ae Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 3 Jul 2023 19:54:33 +0200 Subject: [PATCH 087/163] Use create2 instead of create3 --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 50f568192d..9b1326293d 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -9,7 +9,7 @@ import { BeaconProxyFactory } from "../libraries/ClonableBeaconProxy.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import { CREATE3 } from "solmate/src/utils/CREATE3.sol"; +import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; contract L2AtomicTokenBridgeFactory { address public proxyAdmin; @@ -20,43 +20,55 @@ contract L2AtomicTokenBridgeFactory { function deployRouter( bytes memory creationCode, address l1Router, - address standardGateway + address l2StandardGatewayExpectedAddress ) external { proxyAdmin = address(new ProxyAdmin()); - address routerLogicAddress = CREATE3.deploy( - keccak256(bytes("OrbitL2GatewayRouter")), - creationCode, - 0 + address routerLogicAddress = Create2.deploy( + 0, + keccak256(bytes("OrbitL2GatewayRouterLogic")), + creationCode ); // create proxy router = L2GatewayRouter( - address(new TransparentUpgradeableProxy(routerLogicAddress, proxyAdmin, bytes(""))) + address( + new TransparentUpgradeableProxy{ + salt: keccak256(bytes("OrbitL2GatewayRouterProxy")) + }(routerLogicAddress, proxyAdmin, bytes("")) + ) ); // init proxy - router.initialize(l1Router, address(standardGateway)); + router.initialize(l1Router, l2StandardGatewayExpectedAddress); } function deployStandardGateway(bytes memory creationCode, address l1StandardGateway) external { - address standardGatewayLogicAddress = CREATE3.deploy( - keccak256(bytes("OrbitL2StandardGateway")), - creationCode, - 0 + address standardGatewayLogicAddress = Create2.deploy( + 0, + keccak256(bytes("OrbitL2StandardGatewayLogic")), + creationCode ); // create proxy standardGateway = L2ERC20Gateway( address( - new TransparentUpgradeableProxy(standardGatewayLogicAddress, proxyAdmin, bytes("")) + new TransparentUpgradeableProxy{ + salt: keccak256(bytes("OrbitL2StandardGatewayProxy")) + }(standardGatewayLogicAddress, proxyAdmin, bytes("")) ) ); // create beacon - StandardArbERC20 standardArbERC20 = new StandardArbERC20(); - UpgradeableBeacon beacon = new UpgradeableBeacon(address(standardArbERC20)); - BeaconProxyFactory beaconProxyFactory = new BeaconProxyFactory(); + StandardArbERC20 standardArbERC20 = new StandardArbERC20{ + salt: keccak256(bytes("OrbitStandardArbERC20")) + }(); + UpgradeableBeacon beacon = new UpgradeableBeacon{ + salt: keccak256(bytes("OrbitUpgradeableBeacon")) + }(address(standardArbERC20)); + BeaconProxyFactory beaconProxyFactory = new BeaconProxyFactory{ + salt: keccak256(bytes("OrbitBeaconProxyFactory")) + }(); // init contracts beaconProxyFactory.initialize(address(beacon)); @@ -64,16 +76,18 @@ contract L2AtomicTokenBridgeFactory { } function deployCustomGateway(bytes memory creationCode, address l1CustomGateway) external { - address customGatewayLogicAddress = CREATE3.deploy( - keccak256(bytes("OrbitL2CustomGateway")), - creationCode, - 0 + address customGatewayLogicAddress = Create2.deploy( + 0, + keccak256(bytes("OrbitL2CustomGatewayLogic")), + creationCode ); // create proxy customGateway = L2CustomGateway( address( - new TransparentUpgradeableProxy(customGatewayLogicAddress, proxyAdmin, bytes("")) + new TransparentUpgradeableProxy{ + salt: keccak256(bytes("OrbitL2CustomGatewayProxy")) + }(customGatewayLogicAddress, proxyAdmin, bytes("")) ) ); From fb444a61e50281c4d617ed730dd66e62385a785f Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 4 Jul 2023 10:17:25 +0200 Subject: [PATCH 088/163] Compute expected L2 addresses from L1 creator --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 131 ++++++++++-------- package.json | 3 +- .../atomicTokenBridgeDeployer.ts | 51 ++----- yarn.lock | 5 - 4 files changed, 93 insertions(+), 97 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 6c290f19a5..29e6a23f60 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -10,6 +10,7 @@ import { L2AtomicTokenBridgeFactory } from "../arbitrum/L2AtomicTokenBridgeFacto import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IInbox } from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import { AddressAliasHelper } from "../libraries/AddressAliasHelper.sol"; +import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; contract L1AtomicTokenBridgeCreator is Ownable { event OrbitTokenBridgeCreated( @@ -24,22 +25,33 @@ contract L1AtomicTokenBridgeCreator is Ownable { L1ERC20Gateway public standardGatewayTemplate; L1CustomGateway public customGatewayTemplate; + address public l2TokenBridgeFactoryOnL1; + address public l2RouterOnL1; + address public l2StandardGatewayOnL1; + address public l2CustomGatewayOnL1; + function setTemplates( L1GatewayRouter _router, L1ERC20Gateway _standardGateway, - L1CustomGateway _customGateway + L1CustomGateway _customGateway, + address _l2TokenBridgeFactoryOnL1, + address _l2RouterOnL1, + address _l2StandardGatewayOnL1, + address _l2CustomGatewayOnL1 ) external onlyOwner { routerTemplate = _router; standardGatewayTemplate = _standardGateway; customGatewayTemplate = _customGateway; + + l2TokenBridgeFactoryOnL1 = _l2TokenBridgeFactoryOnL1; + l2RouterOnL1 = _l2RouterOnL1; + l2StandardGatewayOnL1 = _l2StandardGatewayOnL1; + l2CustomGatewayOnL1 = _l2CustomGatewayOnL1; + emit OrbitTokenBridgeTemplatesUpdated(); } function createTokenBridge( - address l2FactoryAddressOnL1, - address l2RouterAddressOnL1, - address l2StandardGatewayAddressOnL1, - address l2CustomGatewayAddressOnL1, address inbox, uint256 maxSubmissionCost, uint256 maxGas, @@ -76,26 +88,32 @@ contract L1AtomicTokenBridgeCreator is Ownable { proxyAdmin ); - _deployL2Factory(l2FactoryAddressOnL1, inbox, maxSubmissionCost, maxGas, gasPriceBid); + _deployL2Factory(inbox, maxSubmissionCost, maxGas, gasPriceBid); + + /// deploy L2 contracts thorugh L2 factory + address l2FactoryExpectedAddress = computeAddress( + AddressAliasHelper.applyL1ToL2Alias(address(this)), + 0 + ); _deployL2Router( - l2RouterAddressOnL1, address(router), + l2FactoryExpectedAddress, inbox, maxSubmissionCost, maxGas, gasPriceBid ); _deployL2StandardGateway( - l2StandardGatewayAddressOnL1, address(standardGateway), + l2FactoryExpectedAddress, inbox, maxSubmissionCost, maxGas, gasPriceBid ); _deployL2CustomGateway( - l2CustomGatewayAddressOnL1, address(customGateway), + l2FactoryExpectedAddress, inbox, maxSubmissionCost, maxGas, @@ -112,14 +130,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { } function _deployL2Factory( - address l2FactoryAddressOnL1, address inbox, uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid ) internal returns (uint256) { // encode L2 factory bytecode - bytes memory deploymentData = creationCodeFor(l2FactoryAddressOnL1.code); + bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryOnL1.code); uint256 value = maxSubmissionCost + maxGas * gasPriceBid; uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( @@ -137,67 +154,50 @@ contract L1AtomicTokenBridgeCreator is Ownable { } function _deployL2Router( - address l2RouterAddressOnL1, address l1Router, + address l2Factory, address inbox, uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid ) internal returns (uint256) { - // encode L2 factory bytecode - bytes memory creationCode = creationCodeFor(l2RouterAddressOnL1.code); - - // address l2StandardGateway = address(1337); + // get L2 factory bytecode + bytes memory creationCode = _creationCodeFor(l2RouterOnL1.code); + /// send retryable + address l2StandardGatewayExpectedAddress = _getExpectedL2StandardGatewayAddress(l2Factory); bytes memory data = abi.encodeWithSelector( L2AtomicTokenBridgeFactory.deployRouter.selector, creationCode, l1Router, - address(1337) - ); - - uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - address l2FactoryAddress = calculateAddress( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - 0 - ); - uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( - l2FactoryAddress, - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - data + l2StandardGatewayExpectedAddress ); + uint256 ticketID = IInbox(inbox).createRetryableTicket{ + value: maxSubmissionCost + maxGas * gasPriceBid + }(l2Factory, 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, data); return ticketID; } function _deployL2StandardGateway( - address l2StandardGatewayAddressOnL1, address l1StandardGateway, + address l2Factory, address inbox, uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid ) internal returns (uint256) { - // encode L2 gateway bytecode - bytes memory creationCode = creationCodeFor(l2StandardGatewayAddressOnL1.code); + // get L2 standard gateway bytecode + bytes memory creationCode = _creationCodeFor(l2StandardGatewayOnL1.code); + /// send retryable bytes memory data = abi.encodeWithSelector( L2AtomicTokenBridgeFactory.deployStandardGateway.selector, creationCode, l1StandardGateway ); - uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - address l2FactoryAddress = calculateAddress( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - 0 - ); uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( - l2FactoryAddress, + l2Factory, 0, maxSubmissionCost, msg.sender, @@ -210,29 +210,25 @@ contract L1AtomicTokenBridgeCreator is Ownable { } function _deployL2CustomGateway( - address l2CustomGatewayAddressOnL1, address l1CustomGateway, + address l2Factory, address inbox, uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid ) internal returns (uint256) { // encode L2 custom gateway bytecode - bytes memory creationCode = creationCodeFor(l2CustomGatewayAddressOnL1.code); + bytes memory creationCode = _creationCodeFor(l2CustomGatewayOnL1.code); + /// send retryable bytes memory data = abi.encodeWithSelector( L2AtomicTokenBridgeFactory.deployCustomGateway.selector, creationCode, l1CustomGateway ); - uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - address l2FactoryAddress = calculateAddress( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - 0 - ); uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( - l2FactoryAddress, + l2Factory, 0, maxSubmissionCost, msg.sender, @@ -244,12 +240,39 @@ contract L1AtomicTokenBridgeCreator is Ownable { return ticketID; } + function _getExpectedL2StandardGatewayAddress( + address deployer + ) internal view returns (address expectedL2StandardGatewayAddress) { + address l2StandardGatewayLogicExpected = Create2.computeAddress( + keccak256(bytes("OrbitL2StandardGatewayLogic")), + keccak256(_creationCodeFor(l2StandardGatewayOnL1.code)), + deployer + ); + + address proxyAdminExpected = Create2.computeAddress( + keccak256(bytes("OrbitL2ProxyAdmin")), + keccak256(type(ProxyAdmin).creationCode), + deployer + ); + + bytes memory tupCode = abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(l2StandardGatewayLogicExpected, proxyAdminExpected, bytes("")) + ); + + expectedL2StandardGatewayAddress = Create2.computeAddress( + keccak256(bytes("OrbitL2StandardGatewayProxy")), + keccak256(tupCode), + deployer + ); + } + /** * @notice Generate a creation code that results on a contract with `_code` as bytecode - * @param _code The returning value of the resulting `creationCode` + * @param code The returning value of the resulting `creationCode` * @return creationCode (constructor) for new contract */ - function creationCodeFor(bytes memory _code) internal pure returns (bytes memory) { + function _creationCodeFor(bytes memory code) internal pure returns (bytes memory) { /* 0x00 0x63 0x63XXXXXX PUSH4 _code.length size 0x01 0x80 0x80 DUP1 size size @@ -262,10 +285,10 @@ contract L1AtomicTokenBridgeCreator is Ownable { */ return - abi.encodePacked(hex"63", uint32(_code.length), hex"80_60_0E_60_00_39_60_00_F3", _code); + abi.encodePacked(hex"63", uint32(code.length), hex"80_60_0E_60_00_39_60_00_F3", code); } - function calculateAddress(address _origin, uint _nonce) public pure returns (address) { + function computeAddress(address _origin, uint _nonce) public pure returns (address) { bytes memory data; if (_nonce == 0x00) data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, bytes1(0x80)); diff --git a/package.json b/package.json index d9ceafd58e..5a0d0bdc63 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,7 @@ "@arbitrum/nitro-contracts": "^1.0.0-beta.8", "@arbitrum/sdk": "^3.1.5", "@openzeppelin/contracts": "4.8.3", - "@openzeppelin/contracts-upgradeable": "4.8.3", - "solmate": "^6.1.0" + "@openzeppelin/contracts-upgradeable": "4.8.3" }, "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.1", diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 2d2f77d145..7e4a0e5d1f 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -109,17 +109,9 @@ export const deployTokenBridgeAndInit = async ( l2Signer: Signer, inboxAddress: string ) => { - // deploy L1 creator + // deploy L1 creator and set templates const l1TokenBridgeCreator = await deployTokenBridgeFactory(l1Signer) - // deploy L2 contracts as templates on L1 - const { - l2TokenBridgeFactoryOnL1, - l2GatewayRouterOnL1, - l2StandardGatewayAddressOnL1, - l2CustomGatewayAddressOnL1, - } = await deployL2TemplatesOnL1(l1Signer) - // create token bridge const maxSubmissionCost = ethers.utils.parseEther('0.1') const maxGas = 10000000 @@ -127,10 +119,6 @@ export const deployTokenBridgeAndInit = async ( const value = gasPriceBid.mul(maxGas).add(maxSubmissionCost).mul(5) const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( - l2TokenBridgeFactoryOnL1.address, - l2GatewayRouterOnL1.address, - l2StandardGatewayAddressOnL1.address, - l2CustomGatewayAddressOnL1.address, inboxAddress, maxSubmissionCost, maxGas, @@ -138,7 +126,6 @@ export const deployTokenBridgeAndInit = async ( { value: value } ) ).wait() - console.log('createTokenBridge done') /// wait for retryable execution const l1TxReceipt = new L1TransactionReceipt(receipt) @@ -277,51 +264,43 @@ const deployTokenBridgeFactory = async (l1Signer: Signer) => { ).deploy() await customGatewayTemplate.deployed() - await ( - await l1TokenBridgeCreator.setTemplates( - routerTemplate.address, - standardGatewayTemplate.address, - customGatewayTemplate.address - ) - ).wait() - - return l1TokenBridgeCreator -} + /// deploy L2 contracts as placeholders on L1 -const deployL2TemplatesOnL1 = async (l1Signer: Signer) => { - /// deploy factory - console.log('Deploy L2AtomicTokenBridgeFactory') const l2TokenBridgeFactoryOnL1 = await new L2AtomicTokenBridgeFactory__factory(l1Signer).deploy() await l2TokenBridgeFactoryOnL1.deployed() /// deploy router - console.log('Deploy L2AtomicTokenBridgeFactory') const l2GatewayRouterOnL1 = await new L2GatewayRouter__factory( l1Signer ).deploy() await l2GatewayRouterOnL1.deployed() /// deploy standard gateway - console.log('Deploy L2ERC20Gateway') const l2StandardGatewayAddressOnL1 = await new L2ERC20Gateway__factory( l1Signer ).deploy() await l2StandardGatewayAddressOnL1.deployed() /// deploy custom gateway - console.log('Deploy L2CustomGateway') const l2CustomGatewayAddressOnL1 = await new L2CustomGateway__factory( l1Signer ).deploy() await l2CustomGatewayAddressOnL1.deployed() - return { - l2TokenBridgeFactoryOnL1, - l2GatewayRouterOnL1, - l2StandardGatewayAddressOnL1, - l2CustomGatewayAddressOnL1, - } + await ( + await l1TokenBridgeCreator.setTemplates( + routerTemplate.address, + standardGatewayTemplate.address, + customGatewayTemplate.address, + l2TokenBridgeFactoryOnL1.address, + l2GatewayRouterOnL1.address, + l2StandardGatewayAddressOnL1.address, + l2CustomGatewayAddressOnL1.address + ) + ).wait() + + return l1TokenBridgeCreator } export const getLocalNetworks = async ( diff --git a/yarn.lock b/yarn.lock index 4d097c1f56..f1118e3a26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9290,11 +9290,6 @@ solidity-coverage@v0.7.17: shelljs "^0.8.3" web3-utils "^1.3.0" -solmate@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/solmate/-/solmate-6.1.0.tgz#b85aaa8c2b34afe9c6d6d5a015c369267c576313" - integrity sha512-gxG4YU5nnAQ+Ac23R44GS3Xo3+X0+8XCe4/P1KvVobL5ERBzQBG/xMv7NSvVo/pkHSYGufgUAPjiueYxujKJAA== - source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" From 94da561f893e42d92f3a00dc4e7a78c5eeaacc08 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 4 Jul 2023 13:26:27 +0200 Subject: [PATCH 089/163] Use computed L2 addresses to init everything properly --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 2 +- .../ethereum/L1AtomicTokenBridgeCreator.sol | 249 +++++++++++++----- .../atomicTokenBridgeDeployer.ts | 2 + 3 files changed, 179 insertions(+), 74 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 9b1326293d..8c81528953 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -22,7 +22,7 @@ contract L2AtomicTokenBridgeFactory { address l1Router, address l2StandardGatewayExpectedAddress ) external { - proxyAdmin = address(new ProxyAdmin()); + proxyAdmin = address(new ProxyAdmin{ salt: keccak256(bytes("OrbitL2ProxyAdmin")) }()); address routerLogicAddress = Create2.deploy( 0, diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 29e6a23f60..a952f9e64e 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -11,6 +11,7 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IInbox } from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import { AddressAliasHelper } from "../libraries/AddressAliasHelper.sol"; import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; +import { BeaconProxyFactory, ClonableBeaconProxy } from "../libraries/ClonableBeaconProxy.sol"; contract L1AtomicTokenBridgeCreator is Ownable { event OrbitTokenBridgeCreated( @@ -30,6 +31,29 @@ contract L1AtomicTokenBridgeCreator is Ownable { address public l2StandardGatewayOnL1; address public l2CustomGatewayOnL1; + address public immutable expectedL2FactoryAddress; + address public immutable expectedL2ProxyAdminAddress; + address public immutable expectedL2BeaconProxyFactoryAddress; + + constructor() Ownable() { + expectedL2FactoryAddress = computeAddress( + AddressAliasHelper.applyL1ToL2Alias(address(this)), + 0 + ); + + expectedL2ProxyAdminAddress = Create2.computeAddress( + keccak256(bytes("OrbitL2ProxyAdmin")), + keccak256(type(ProxyAdmin).creationCode), + expectedL2FactoryAddress + ); + + expectedL2BeaconProxyFactoryAddress = Create2.computeAddress( + keccak256(bytes("OrbitBeaconProxyFactory")), + keccak256(type(BeaconProxyFactory).creationCode), + expectedL2FactoryAddress + ); + } + function setTemplates( L1GatewayRouter _router, L1ERC20Gateway _standardGateway, @@ -53,6 +77,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { function createTokenBridge( address inbox, + address owner, uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid @@ -62,23 +87,25 @@ contract L1AtomicTokenBridgeCreator is Ownable { L1GatewayRouter router = L1GatewayRouter( address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes(""))) ); - L1ERC20Gateway standardGateway = L1ERC20Gateway( - address( - new TransparentUpgradeableProxy( - address(standardGatewayTemplate), - proxyAdmin, - bytes("") - ) - ) + L1ERC20Gateway standardGateway = _deployL1StandardGateway( + proxyAdmin, + address(router), + inbox ); - L1CustomGateway customGateway = L1CustomGateway( - address( - new TransparentUpgradeableProxy( - address(customGatewayTemplate), - proxyAdmin, - bytes("") - ) - ) + L1CustomGateway customGateway = _deployL1CustomGateway( + proxyAdmin, + address(router), + inbox, + owner + ); + + // init router + router.initialize( + owner, + address(standardGateway), + address(0), + _computeExpectedL2RouterAddress(), + inbox ); emit OrbitTokenBridgeCreated( @@ -90,22 +117,10 @@ contract L1AtomicTokenBridgeCreator is Ownable { _deployL2Factory(inbox, maxSubmissionCost, maxGas, gasPriceBid); - /// deploy L2 contracts thorugh L2 factory - address l2FactoryExpectedAddress = computeAddress( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - 0 - ); - _deployL2Router( - address(router), - l2FactoryExpectedAddress, - inbox, - maxSubmissionCost, - maxGas, - gasPriceBid - ); + /// deploy L2 contracts through L2 factory + _deployL2Router(address(router), inbox, maxSubmissionCost, maxGas, gasPriceBid); _deployL2StandardGateway( address(standardGateway), - l2FactoryExpectedAddress, inbox, maxSubmissionCost, maxGas, @@ -113,20 +128,63 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); _deployL2CustomGateway( address(customGateway), - l2FactoryExpectedAddress, inbox, maxSubmissionCost, maxGas, gasPriceBid ); + } + + function _deployL1StandardGateway( + address proxyAdmin, + address router, + address inbox + ) internal returns (L1ERC20Gateway) { + L1ERC20Gateway standardGateway = L1ERC20Gateway( + address( + new TransparentUpgradeableProxy( + address(standardGatewayTemplate), + proxyAdmin, + bytes("") + ) + ) + ); + + standardGateway.initialize( + _computeExpectedL2StandardGatewayAddress(), + router, + inbox, + keccak256(type(ClonableBeaconProxy).creationCode), + expectedL2BeaconProxyFactoryAddress + ); - //// init contracts - // { - // /// dependencies - l2Router, l2StandardGateway, l2CustomGateway, cloneableProxyHash, l2BeaconProxyFactory, owner, inbox - // router.initialize(address(1), address(standardGateway), address(0), address(1), inbox); - // standardGateway.initialize(address(1), address(router), inbox, "abc", address(1)); - // customGateway.initialize(address(1), address(router), inbox, address(1)); - // } + return standardGateway; + } + + function _deployL1CustomGateway( + address proxyAdmin, + address router, + address inbox, + address owner + ) internal returns (L1CustomGateway) { + L1CustomGateway customGateway = L1CustomGateway( + address( + new TransparentUpgradeableProxy( + address(customGatewayTemplate), + proxyAdmin, + bytes("") + ) + ) + ); + + customGateway.initialize( + _computeExpectedL2CustomGatewayAddress(), + address(router), + inbox, + owner + ); + + return customGateway; } function _deployL2Factory( @@ -155,7 +213,6 @@ contract L1AtomicTokenBridgeCreator is Ownable { function _deployL2Router( address l1Router, - address l2Factory, address inbox, uint256 maxSubmissionCost, uint256 maxGas, @@ -165,22 +222,29 @@ contract L1AtomicTokenBridgeCreator is Ownable { bytes memory creationCode = _creationCodeFor(l2RouterOnL1.code); /// send retryable - address l2StandardGatewayExpectedAddress = _getExpectedL2StandardGatewayAddress(l2Factory); bytes memory data = abi.encodeWithSelector( L2AtomicTokenBridgeFactory.deployRouter.selector, creationCode, l1Router, - l2StandardGatewayExpectedAddress + _computeExpectedL2StandardGatewayAddress() ); uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: maxSubmissionCost + maxGas * gasPriceBid - }(l2Factory, 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, data); + }( + expectedL2FactoryAddress, + 0, + maxSubmissionCost, + msg.sender, + msg.sender, + maxGas, + gasPriceBid, + data + ); return ticketID; } function _deployL2StandardGateway( address l1StandardGateway, - address l2Factory, address inbox, uint256 maxSubmissionCost, uint256 maxGas, @@ -197,7 +261,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); uint256 value = maxSubmissionCost + maxGas * gasPriceBid; uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( - l2Factory, + expectedL2FactoryAddress, 0, maxSubmissionCost, msg.sender, @@ -211,7 +275,6 @@ contract L1AtomicTokenBridgeCreator is Ownable { function _deployL2CustomGateway( address l1CustomGateway, - address l2Factory, address inbox, uint256 maxSubmissionCost, uint256 maxGas, @@ -228,7 +291,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); uint256 value = maxSubmissionCost + maxGas * gasPriceBid; uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( - l2Factory, + expectedL2FactoryAddress, 0, maxSubmissionCost, msg.sender, @@ -240,33 +303,6 @@ contract L1AtomicTokenBridgeCreator is Ownable { return ticketID; } - function _getExpectedL2StandardGatewayAddress( - address deployer - ) internal view returns (address expectedL2StandardGatewayAddress) { - address l2StandardGatewayLogicExpected = Create2.computeAddress( - keccak256(bytes("OrbitL2StandardGatewayLogic")), - keccak256(_creationCodeFor(l2StandardGatewayOnL1.code)), - deployer - ); - - address proxyAdminExpected = Create2.computeAddress( - keccak256(bytes("OrbitL2ProxyAdmin")), - keccak256(type(ProxyAdmin).creationCode), - deployer - ); - - bytes memory tupCode = abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(l2StandardGatewayLogicExpected, proxyAdminExpected, bytes("")) - ); - - expectedL2StandardGatewayAddress = Create2.computeAddress( - keccak256(bytes("OrbitL2StandardGatewayProxy")), - keccak256(tupCode), - deployer - ); - } - /** * @notice Generate a creation code that results on a contract with `_code` as bytecode * @param code The returning value of the resulting `creationCode` @@ -328,4 +364,71 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); return address(uint160(uint256(keccak256(data)))); } + + function _computeExpectedL2RouterAddress() internal returns (address) { + address expectedL2RouterLogic = Create2.computeAddress( + keccak256(bytes("OrbitL2GatewayRouterLogic")), + keccak256(_creationCodeFor(l2RouterOnL1.code)), + expectedL2FactoryAddress + ); + + return + Create2.computeAddress( + keccak256(bytes("OrbitL2GatewayRouterProxy")), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(expectedL2RouterLogic, expectedL2ProxyAdminAddress, bytes("")) + ) + ), + expectedL2FactoryAddress + ); + } + + function _computeExpectedL2StandardGatewayAddress() internal view returns (address) { + address expectedL2StandardGatewayLogic = Create2.computeAddress( + keccak256(bytes("OrbitL2StandardGatewayLogic")), + keccak256(_creationCodeFor(l2StandardGatewayOnL1.code)), + expectedL2FactoryAddress + ); + return + Create2.computeAddress( + keccak256(bytes("OrbitL2StandardGatewayProxy")), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode( + expectedL2StandardGatewayLogic, + expectedL2ProxyAdminAddress, + bytes("") + ) + ) + ), + expectedL2FactoryAddress + ); + } + + function _computeExpectedL2CustomGatewayAddress() internal view returns (address) { + address expectedL2CustomGatewayLogic = Create2.computeAddress( + keccak256(bytes("OrbitL2CustomGatewayLogic")), + keccak256(_creationCodeFor(l2CustomGatewayOnL1.code)), + expectedL2FactoryAddress + ); + + return + Create2.computeAddress( + keccak256(bytes("OrbitL2CustomGatewayProxy")), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode( + expectedL2CustomGatewayLogic, + expectedL2ProxyAdminAddress, + bytes("") + ) + ) + ), + expectedL2FactoryAddress + ); + } } diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 7e4a0e5d1f..0e6fdbe0cd 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -117,9 +117,11 @@ export const deployTokenBridgeAndInit = async ( const maxGas = 10000000 const gasPriceBid = ethers.utils.parseUnits('0.5', 'gwei') const value = gasPriceBid.mul(maxGas).add(maxSubmissionCost).mul(5) + const owner = await l1Signer.getAddress() const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( inboxAddress, + owner, maxSubmissionCost, maxGas, gasPriceBid, From a9e9d562d86be0deed7780af5fcb01bc72b753ca Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 4 Jul 2023 14:10:26 +0200 Subject: [PATCH 090/163] Use library for L2 salts --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 77 +++++++++++-------- .../ethereum/L1AtomicTokenBridgeCreator.sol | 62 +++++++-------- 2 files changed, 78 insertions(+), 61 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 8c81528953..b57a5b2386 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -22,52 +22,49 @@ contract L2AtomicTokenBridgeFactory { address l1Router, address l2StandardGatewayExpectedAddress ) external { - proxyAdmin = address(new ProxyAdmin{ salt: keccak256(bytes("OrbitL2ProxyAdmin")) }()); + // first create proxyAdmin which will be used for all contracts + proxyAdmin = address(new ProxyAdmin{ salt: L2Salts.PROXY_ADMIN }()); - address routerLogicAddress = Create2.deploy( - 0, - keccak256(bytes("OrbitL2GatewayRouterLogic")), - creationCode - ); - - // create proxy + // create logic and proxy + address routerLogicAddress = Create2.deploy(0, L2Salts.ROUTER_LOGIC, creationCode); router = L2GatewayRouter( address( - new TransparentUpgradeableProxy{ - salt: keccak256(bytes("OrbitL2GatewayRouterProxy")) - }(routerLogicAddress, proxyAdmin, bytes("")) + new TransparentUpgradeableProxy{ salt: L2Salts.ROUTER }( + routerLogicAddress, + proxyAdmin, + bytes("") + ) ) ); - // init proxy + // init router.initialize(l1Router, l2StandardGatewayExpectedAddress); } function deployStandardGateway(bytes memory creationCode, address l1StandardGateway) external { + // create logic and proxy address standardGatewayLogicAddress = Create2.deploy( 0, - keccak256(bytes("OrbitL2StandardGatewayLogic")), + L2Salts.STANDARD_GATEWAY_LOGIC, creationCode ); - - // create proxy standardGateway = L2ERC20Gateway( address( - new TransparentUpgradeableProxy{ - salt: keccak256(bytes("OrbitL2StandardGatewayProxy")) - }(standardGatewayLogicAddress, proxyAdmin, bytes("")) + new TransparentUpgradeableProxy{ salt: L2Salts.STANDARD_GATEWAY }( + standardGatewayLogicAddress, + proxyAdmin, + bytes("") + ) ) ); // create beacon - StandardArbERC20 standardArbERC20 = new StandardArbERC20{ - salt: keccak256(bytes("OrbitStandardArbERC20")) - }(); - UpgradeableBeacon beacon = new UpgradeableBeacon{ - salt: keccak256(bytes("OrbitUpgradeableBeacon")) - }(address(standardArbERC20)); + StandardArbERC20 standardArbERC20 = new StandardArbERC20{ salt: L2Salts.STANDARD_ERC20 }(); + UpgradeableBeacon beacon = new UpgradeableBeacon{ salt: L2Salts.UPGRADEABLE_BEACON }( + address(standardArbERC20) + ); BeaconProxyFactory beaconProxyFactory = new BeaconProxyFactory{ - salt: keccak256(bytes("OrbitBeaconProxyFactory")) + salt: L2Salts.BEACON_PROXY_FACTORY }(); // init contracts @@ -78,19 +75,39 @@ contract L2AtomicTokenBridgeFactory { function deployCustomGateway(bytes memory creationCode, address l1CustomGateway) external { address customGatewayLogicAddress = Create2.deploy( 0, - keccak256(bytes("OrbitL2CustomGatewayLogic")), + L2Salts.CUSTOM_GATEWAY_LOGIC, creationCode ); - // create proxy + // create logic and proxy customGateway = L2CustomGateway( address( - new TransparentUpgradeableProxy{ - salt: keccak256(bytes("OrbitL2CustomGatewayProxy")) - }(customGatewayLogicAddress, proxyAdmin, bytes("")) + new TransparentUpgradeableProxy{ salt: L2Salts.CUSTOM_GATEWAY }( + customGatewayLogicAddress, + proxyAdmin, + bytes("") + ) ) ); + // init customGateway.initialize(l1CustomGateway, address(router)); } } + +/** + * Collection of salts used in CREATE2 deployment of L2 token bridge contracts. + */ +library L2Salts { + bytes32 public constant PROXY_ADMIN = keccak256(bytes("OrbitL2ProxyAdmin")); + bytes32 public constant ROUTER_LOGIC = keccak256(bytes("OrbitL2GatewayRouterLogic")); + bytes32 public constant ROUTER = keccak256(bytes("OrbitL2GatewayRouterProxy")); + bytes32 public constant STANDARD_GATEWAY_LOGIC = + keccak256(bytes("OrbitL2StandardGatewayLogic")); + bytes32 public constant STANDARD_GATEWAY = keccak256(bytes("OrbitL2StandardGatewayProxy")); + bytes32 public constant CUSTOM_GATEWAY_LOGIC = keccak256(bytes("OrbitL2CustomGatewayLogic")); + bytes32 public constant CUSTOM_GATEWAY = keccak256(bytes("OrbitL2CustomGatewayProxy")); + bytes32 public constant STANDARD_ERC20 = keccak256(bytes("OrbitStandardArbERC20")); + bytes32 public constant UPGRADEABLE_BEACON = keccak256(bytes("OrbitUpgradeableBeacon")); + bytes32 public constant BEACON_PROXY_FACTORY = keccak256(bytes("OrbitBeaconProxyFactory")); +} diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index a952f9e64e..f500f99a42 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -6,7 +6,7 @@ import { L1ERC20Gateway } from "./gateway/L1ERC20Gateway.sol"; import { L1CustomGateway } from "./gateway/L1CustomGateway.sol"; import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import { L2AtomicTokenBridgeFactory } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; +import { L2AtomicTokenBridgeFactory, L2Salts } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IInbox } from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import { AddressAliasHelper } from "../libraries/AddressAliasHelper.sol"; @@ -26,29 +26,29 @@ contract L1AtomicTokenBridgeCreator is Ownable { L1ERC20Gateway public standardGatewayTemplate; L1CustomGateway public customGatewayTemplate; - address public l2TokenBridgeFactoryOnL1; - address public l2RouterOnL1; - address public l2StandardGatewayOnL1; - address public l2CustomGatewayOnL1; + address public l2TokenBridgeFactoryTemplate; + address public l2RouterTemplate; + address public l2StandardGatewayTemplate; + address public l2CustomGatewayTemplate; address public immutable expectedL2FactoryAddress; address public immutable expectedL2ProxyAdminAddress; address public immutable expectedL2BeaconProxyFactoryAddress; constructor() Ownable() { - expectedL2FactoryAddress = computeAddress( + expectedL2FactoryAddress = _computeAddress( AddressAliasHelper.applyL1ToL2Alias(address(this)), 0 ); expectedL2ProxyAdminAddress = Create2.computeAddress( - keccak256(bytes("OrbitL2ProxyAdmin")), + L2Salts.PROXY_ADMIN, keccak256(type(ProxyAdmin).creationCode), expectedL2FactoryAddress ); expectedL2BeaconProxyFactoryAddress = Create2.computeAddress( - keccak256(bytes("OrbitBeaconProxyFactory")), + L2Salts.BEACON_PROXY_FACTORY, keccak256(type(BeaconProxyFactory).creationCode), expectedL2FactoryAddress ); @@ -58,19 +58,19 @@ contract L1AtomicTokenBridgeCreator is Ownable { L1GatewayRouter _router, L1ERC20Gateway _standardGateway, L1CustomGateway _customGateway, - address _l2TokenBridgeFactoryOnL1, - address _l2RouterOnL1, - address _l2StandardGatewayOnL1, - address _l2CustomGatewayOnL1 + address _l2TokenBridgeFactoryTemplate, + address _l2RouterTemplate, + address _l2StandardGatewayTemplate, + address _l2CustomGatewayTemplate ) external onlyOwner { routerTemplate = _router; standardGatewayTemplate = _standardGateway; customGatewayTemplate = _customGateway; - l2TokenBridgeFactoryOnL1 = _l2TokenBridgeFactoryOnL1; - l2RouterOnL1 = _l2RouterOnL1; - l2StandardGatewayOnL1 = _l2StandardGatewayOnL1; - l2CustomGatewayOnL1 = _l2CustomGatewayOnL1; + l2TokenBridgeFactoryTemplate = _l2TokenBridgeFactoryTemplate; + l2RouterTemplate = _l2RouterTemplate; + l2StandardGatewayTemplate = _l2StandardGatewayTemplate; + l2CustomGatewayTemplate = _l2CustomGatewayTemplate; emit OrbitTokenBridgeTemplatesUpdated(); } @@ -194,7 +194,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 gasPriceBid ) internal returns (uint256) { // encode L2 factory bytecode - bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryOnL1.code); + bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); uint256 value = maxSubmissionCost + maxGas * gasPriceBid; uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( @@ -219,7 +219,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 gasPriceBid ) internal returns (uint256) { // get L2 factory bytecode - bytes memory creationCode = _creationCodeFor(l2RouterOnL1.code); + bytes memory creationCode = _creationCodeFor(l2RouterTemplate.code); /// send retryable bytes memory data = abi.encodeWithSelector( @@ -251,7 +251,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 gasPriceBid ) internal returns (uint256) { // get L2 standard gateway bytecode - bytes memory creationCode = _creationCodeFor(l2StandardGatewayOnL1.code); + bytes memory creationCode = _creationCodeFor(l2StandardGatewayTemplate.code); /// send retryable bytes memory data = abi.encodeWithSelector( @@ -281,7 +281,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 gasPriceBid ) internal returns (uint256) { // encode L2 custom gateway bytecode - bytes memory creationCode = _creationCodeFor(l2CustomGatewayOnL1.code); + bytes memory creationCode = _creationCodeFor(l2CustomGatewayTemplate.code); /// send retryable bytes memory data = abi.encodeWithSelector( @@ -324,7 +324,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { abi.encodePacked(hex"63", uint32(code.length), hex"80_60_0E_60_00_39_60_00_F3", code); } - function computeAddress(address _origin, uint _nonce) public pure returns (address) { + function _computeAddress(address _origin, uint _nonce) public pure returns (address) { bytes memory data; if (_nonce == 0x00) data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, bytes1(0x80)); @@ -365,16 +365,16 @@ contract L1AtomicTokenBridgeCreator is Ownable { return address(uint160(uint256(keccak256(data)))); } - function _computeExpectedL2RouterAddress() internal returns (address) { + function _computeExpectedL2RouterAddress() internal view returns (address) { address expectedL2RouterLogic = Create2.computeAddress( - keccak256(bytes("OrbitL2GatewayRouterLogic")), - keccak256(_creationCodeFor(l2RouterOnL1.code)), + L2Salts.ROUTER_LOGIC, + keccak256(_creationCodeFor(l2RouterTemplate.code)), expectedL2FactoryAddress ); return Create2.computeAddress( - keccak256(bytes("OrbitL2GatewayRouterProxy")), + L2Salts.ROUTER, keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, @@ -387,13 +387,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { function _computeExpectedL2StandardGatewayAddress() internal view returns (address) { address expectedL2StandardGatewayLogic = Create2.computeAddress( - keccak256(bytes("OrbitL2StandardGatewayLogic")), - keccak256(_creationCodeFor(l2StandardGatewayOnL1.code)), + L2Salts.STANDARD_GATEWAY_LOGIC, + keccak256(_creationCodeFor(l2StandardGatewayTemplate.code)), expectedL2FactoryAddress ); return Create2.computeAddress( - keccak256(bytes("OrbitL2StandardGatewayProxy")), + L2Salts.STANDARD_GATEWAY, keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, @@ -410,14 +410,14 @@ contract L1AtomicTokenBridgeCreator is Ownable { function _computeExpectedL2CustomGatewayAddress() internal view returns (address) { address expectedL2CustomGatewayLogic = Create2.computeAddress( - keccak256(bytes("OrbitL2CustomGatewayLogic")), - keccak256(_creationCodeFor(l2CustomGatewayOnL1.code)), + L2Salts.CUSTOM_GATEWAY_LOGIC, + keccak256(_creationCodeFor(l2CustomGatewayTemplate.code)), expectedL2FactoryAddress ); return Create2.computeAddress( - keccak256(bytes("OrbitL2CustomGatewayProxy")), + L2Salts.CUSTOM_GATEWAY, keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, From 093b26bb92b0405d8df060fcd572edd7f1caade0 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 4 Jul 2023 16:03:17 +0200 Subject: [PATCH 091/163] Use 2 retryables instead of 4 --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 22 ++- .../ethereum/L1AtomicTokenBridgeCreator.sol | 181 ++++++------------ .../atomicTokenBridgeDeployer.ts | 97 ++++------ 3 files changed, 110 insertions(+), 190 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index b57a5b2386..f0430ccdf3 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -17,11 +17,25 @@ contract L2AtomicTokenBridgeFactory { L2ERC20Gateway public standardGateway; L2CustomGateway public customGateway; - function deployRouter( - bytes memory creationCode, + function deployL2Contracts( + bytes memory routerCreationCode, + bytes memory standardGatewayCreationCode, + bytes memory customGatewayCreationCode, address l1Router, + address l1StandardGateway, + address l1CustomGateway, address l2StandardGatewayExpectedAddress ) external { + _deployRouter(routerCreationCode, l1Router, l2StandardGatewayExpectedAddress); + _deployStandardGateway(standardGatewayCreationCode, l1StandardGateway); + _deployCustomGateway(customGatewayCreationCode, l1CustomGateway); + } + + function _deployRouter( + bytes memory creationCode, + address l1Router, + address l2StandardGatewayExpectedAddress + ) internal { // first create proxyAdmin which will be used for all contracts proxyAdmin = address(new ProxyAdmin{ salt: L2Salts.PROXY_ADMIN }()); @@ -41,7 +55,7 @@ contract L2AtomicTokenBridgeFactory { router.initialize(l1Router, l2StandardGatewayExpectedAddress); } - function deployStandardGateway(bytes memory creationCode, address l1StandardGateway) external { + function _deployStandardGateway(bytes memory creationCode, address l1StandardGateway) internal { // create logic and proxy address standardGatewayLogicAddress = Create2.deploy( 0, @@ -72,7 +86,7 @@ contract L2AtomicTokenBridgeFactory { standardGateway.initialize(l1StandardGateway, address(router), address(beaconProxyFactory)); } - function deployCustomGateway(bytes memory creationCode, address l1CustomGateway) external { + function _deployCustomGateway(bytes memory creationCode, address l1CustomGateway) internal { address customGatewayLogicAddress = Create2.deploy( 0, L2Salts.CUSTOM_GATEWAY_LOGIC, diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index f500f99a42..48e296e040 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -115,23 +115,72 @@ contract L1AtomicTokenBridgeCreator is Ownable { proxyAdmin ); + /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls _deployL2Factory(inbox, maxSubmissionCost, maxGas, gasPriceBid); - - /// deploy L2 contracts through L2 factory - _deployL2Router(address(router), inbox, maxSubmissionCost, maxGas, gasPriceBid); - _deployL2StandardGateway( + _deployL2Contracts( + address(router), address(standardGateway), + address(customGateway), inbox, maxSubmissionCost, maxGas, gasPriceBid ); - _deployL2CustomGateway( - address(customGateway), - inbox, + } + + function _deployL2Factory( + address inbox, + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 gasPriceBid + ) internal returns (uint256) { + // encode L2 factory bytecode + bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); + + uint256 value = maxSubmissionCost + maxGas * gasPriceBid; + uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( + address(0), + 0, maxSubmissionCost, + msg.sender, + msg.sender, maxGas, - gasPriceBid + gasPriceBid, + deploymentData + ); + + return ticketID; + } + + function _deployL2Contracts( + address l1Router, + address l1StandardGateway, + address l1CustomGateway, + address inbox, + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 gasPriceBid + ) internal { + bytes memory data = abi.encodeWithSelector( + L2AtomicTokenBridgeFactory.deployL2Contracts.selector, + _creationCodeFor(l2RouterTemplate.code), + _creationCodeFor(l2StandardGatewayTemplate.code), + _creationCodeFor(l2CustomGatewayTemplate.code), + l1Router, + l1StandardGateway, + l1CustomGateway, + _computeExpectedL2StandardGatewayAddress() + ); + + IInbox(inbox).createRetryableTicket{ value: maxSubmissionCost + maxGas * gasPriceBid }( + expectedL2FactoryAddress, + 0, + maxSubmissionCost, + msg.sender, + msg.sender, + maxGas, + gasPriceBid, + data ); } @@ -187,122 +236,6 @@ contract L1AtomicTokenBridgeCreator is Ownable { return customGateway; } - function _deployL2Factory( - address inbox, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) internal returns (uint256) { - // encode L2 factory bytecode - bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); - - uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( - address(0), - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - deploymentData - ); - - return ticketID; - } - - function _deployL2Router( - address l1Router, - address inbox, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) internal returns (uint256) { - // get L2 factory bytecode - bytes memory creationCode = _creationCodeFor(l2RouterTemplate.code); - - /// send retryable - bytes memory data = abi.encodeWithSelector( - L2AtomicTokenBridgeFactory.deployRouter.selector, - creationCode, - l1Router, - _computeExpectedL2StandardGatewayAddress() - ); - uint256 ticketID = IInbox(inbox).createRetryableTicket{ - value: maxSubmissionCost + maxGas * gasPriceBid - }( - expectedL2FactoryAddress, - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - data - ); - return ticketID; - } - - function _deployL2StandardGateway( - address l1StandardGateway, - address inbox, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) internal returns (uint256) { - // get L2 standard gateway bytecode - bytes memory creationCode = _creationCodeFor(l2StandardGatewayTemplate.code); - - /// send retryable - bytes memory data = abi.encodeWithSelector( - L2AtomicTokenBridgeFactory.deployStandardGateway.selector, - creationCode, - l1StandardGateway - ); - uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( - expectedL2FactoryAddress, - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - data - ); - return ticketID; - } - - function _deployL2CustomGateway( - address l1CustomGateway, - address inbox, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) internal returns (uint256) { - // encode L2 custom gateway bytecode - bytes memory creationCode = _creationCodeFor(l2CustomGatewayTemplate.code); - - /// send retryable - bytes memory data = abi.encodeWithSelector( - L2AtomicTokenBridgeFactory.deployCustomGateway.selector, - creationCode, - l1CustomGateway - ); - uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( - expectedL2FactoryAddress, - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - data - ); - return ticketID; - } - /** * @notice Generate a creation code that results on a contract with `_code` as bytecode * @param code The returning value of the resulting `creationCode` diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 0e6fdbe0cd..e20305228d 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -1,4 +1,4 @@ -import { Contract, Signer, Wallet, ethers } from 'ethers' +import { Signer, Wallet, ethers } from 'ethers' import { L1CustomGateway__factory, L1ERC20Gateway__factory, @@ -8,6 +8,7 @@ import { L2GatewayRouter__factory, L2ERC20Gateway__factory, L2CustomGateway__factory, + L1AtomicTokenBridgeCreator, } from '../../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { @@ -34,6 +35,7 @@ export const setupTokenBridge = async ( l2Url ) + // register - needed for retryables addCustomNetwork({ customL1Network: l1Network, customL2Network: { @@ -58,9 +60,14 @@ export const setupTokenBridge = async ( }, }) - const deployedContracts = await deployTokenBridgeAndInit( + // prerequisite - deploy L1 creator and set templates + const l1TokenBridgeCreator = await deployL1TokenBridgeCreator(l1Deployer) + + // create token bridge + const deployedContracts = await createTokenBridge( l1Deployer, l2Deployer, + l1TokenBridgeCreator, coreL2Network.ethBridge.inbox ) @@ -85,6 +92,7 @@ export const setupTokenBridge = async ( }, } + // can't re-add // addCustomNetwork({ // customL1Network: l1Network, // customL2Network: l2Network, @@ -97,21 +105,19 @@ export const setupTokenBridge = async ( } /** - * Deploy all the L1 and L2 contracts and do the initialization. + * Use already deployed L1TokenBridgeCreator to create and token bridge contracts. * * @param l1Signer * @param l2Signer * @param inboxAddress * @returns */ -export const deployTokenBridgeAndInit = async ( +export const createTokenBridge = async ( l1Signer: Signer, l2Signer: Signer, + l1TokenBridgeCreator: L1AtomicTokenBridgeCreator, inboxAddress: string ) => { - // deploy L1 creator and set templates - const l1TokenBridgeCreator = await deployTokenBridgeFactory(l1Signer) - // create token bridge const maxSubmissionCost = ethers.utils.parseEther('0.1') const maxGas = 10000000 @@ -132,59 +138,37 @@ export const deployTokenBridgeAndInit = async ( /// wait for retryable execution const l1TxReceipt = new L1TransactionReceipt(receipt) const messages = await l1TxReceipt.getL1ToL2Messages(l2Signer) + const messageResults = await Promise.all( + messages.map(message => message.waitForStatus()) + ) - // 1st msg - deploy factory - const messageResult = await messages[0].waitForStatus() - if (messageResult.status !== L1ToL2MessageStatus.REDEEMED) { - console.error( - `1 L2 retryable ticket is failed with status ${ - L1ToL2MessageStatus[messageResult.status] + // if both tickets are not redeemed log it and exit + if ( + messageResults[0].status !== L1ToL2MessageStatus.REDEEMED || + messageResults[1].status !== L1ToL2MessageStatus.REDEEMED + ) { + console.log( + `Retryable ticket (ID ${messages[0].retryableCreationId}) status: ${ + L1ToL2MessageStatus[messageResults[0].status] + }` + ) + console.log( + `Retryable ticket (ID ${messages[1].retryableCreationId}) status: ${ + L1ToL2MessageStatus[messageResults[1].status] }` ) exit() } + /// pick up L2 factory address from 1st ticket const l2AtomicTokenBridgeFactory = L2AtomicTokenBridgeFactory__factory.connect( - messageResult.l2TxReceipt.contractAddress, + messageResults[0].l2TxReceipt.contractAddress, l2Signer ) console.log('L2AtomicTokenBridgeFactory', l2AtomicTokenBridgeFactory.address) - // 2nd msg - deploy router - const messageRouterResult = await messages[1].waitForStatus() - if (messageRouterResult.status !== L1ToL2MessageStatus.REDEEMED) { - console.error( - `2 L2 retryable ticket is failed with status ${ - L1ToL2MessageStatus[messageRouterResult.status] - }` - ) - exit() - } - - // 3rd msg - deploy standard gw - const messageStdGwResult = await messages[2].waitForStatus() - if (messageRouterResult.status !== L1ToL2MessageStatus.REDEEMED) { - console.error( - `3 L2 retryable ticket is failed with status ${ - L1ToL2MessageStatus[messageStdGwResult.status] - }` - ) - exit() - } - - // 4th msg - deploy custom gw - const messageCustomGwResult = await messages[3].waitForStatus() - if (messageCustomGwResult.status !== L1ToL2MessageStatus.REDEEMED) { - console.error( - `4 L2 retryable ticket is failed with status ${ - L1ToL2MessageStatus[messageCustomGwResult.status] - }` - ) - exit() - } - - /// get L1 deployed contracts + /// pick up L1 contracts from events const { router: l1Router, standardGateway: l1StandardGateway, @@ -196,21 +180,14 @@ export const deployTokenBridgeAndInit = async ( 'OrbitTokenBridgeCreated' )[0].args - /// get L2 router + /// pick up L2 contracts from L1 factory contract const l2Router = await l2AtomicTokenBridgeFactory.router() - - /// get L2 standard gateway const l2StandardGateway = L2ERC20Gateway__factory.connect( await l2AtomicTokenBridgeFactory.standardGateway(), l2Signer ) const beaconProxyFactory = await l2StandardGateway.beaconProxyFactory() - - /// get L2 standard gateway const l2CustomGateway = await l2AtomicTokenBridgeFactory.customGateway() - console.log('l2CustomGateway', l2CustomGateway) - - /// get L2 proxy admin const l2ProxyAdmin = await l2AtomicTokenBridgeFactory.proxyAdmin() return { @@ -240,19 +217,15 @@ const getParsedLogs = ( return parsedLogs } -const deployTokenBridgeFactory = async (l1Signer: Signer) => { +const deployL1TokenBridgeCreator = async (l1Signer: Signer) => { /// deploy factory - console.log('Deploy L1AtomicTokenBridgeCreator') - const l1TokenBridgeCreator = await new L1AtomicTokenBridgeCreator__factory( l1Signer ).deploy() await l1TokenBridgeCreator.deployed() - console.log('l1TokenBridgeCreator', l1TokenBridgeCreator.address) + console.log('L1TokenBridgeCreator', l1TokenBridgeCreator.address) /// deploy logic contracts - console.log('Create and set logic contracts') - const routerTemplate = await new L1GatewayRouter__factory(l1Signer).deploy() await routerTemplate.deployed() From 097c5265660f6291cf45431fa114b02be6ae26de Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Jul 2023 09:18:07 +0200 Subject: [PATCH 092/163] Estimate gas for retryables instead of hard-coding it --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 163 +++++++++--------- .../atomicTokenBridgeDeployer.ts | 71 ++++++-- test-e2e/tokenBridgeDeploymentTest.ts | 20 ++- 3 files changed, 154 insertions(+), 100 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 48e296e040..8f39de26f5 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -78,29 +78,47 @@ contract L1AtomicTokenBridgeCreator is Ownable { function createTokenBridge( address inbox, address owner, - uint256 maxSubmissionCost, - uint256 maxGas, + uint256 maxSubmissionCostForFactory, + uint256 maxGasForFactory, + uint256 maxSubmissionCostForContracts, + uint256 maxGasForContracts, uint256 gasPriceBid ) external payable { - address proxyAdmin = address(new ProxyAdmin()); - - L1GatewayRouter router = L1GatewayRouter( - address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes(""))) - ); - L1ERC20Gateway standardGateway = _deployL1StandardGateway( - proxyAdmin, - address(router), - inbox + (address router, address standardGateway, address customGateway) = _deployL1Contracts( + inbox, + owner ); - L1CustomGateway customGateway = _deployL1CustomGateway( - proxyAdmin, + + /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls + _deployL2Factory(inbox, maxSubmissionCostForFactory, maxGasForFactory, gasPriceBid); + _deployL2Contracts( address(router), + address(standardGateway), + address(customGateway), inbox, - owner + maxSubmissionCostForContracts, + maxGasForContracts, + gasPriceBid ); + } + + function _deployL1Contracts( + address inbox, + address owner + ) internal returns (address router, address standardGateway, address customGateway) { + address proxyAdmin = address(new ProxyAdmin()); + + // deploy router + router = address( + new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes("")) + ); + + // deploy and init gateways + standardGateway = _deployL1StandardGateway(proxyAdmin, address(router), inbox); + customGateway = _deployL1CustomGateway(proxyAdmin, address(router), inbox, owner); // init router - router.initialize( + L1GatewayRouter(router).initialize( owner, address(standardGateway), address(0), @@ -108,24 +126,65 @@ contract L1AtomicTokenBridgeCreator is Ownable { inbox ); + // emit it emit OrbitTokenBridgeCreated( address(router), address(standardGateway), address(customGateway), proxyAdmin ); + } - /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls - _deployL2Factory(inbox, maxSubmissionCost, maxGas, gasPriceBid); - _deployL2Contracts( + function _deployL1StandardGateway( + address proxyAdmin, + address router, + address inbox + ) internal returns (address) { + L1ERC20Gateway standardGateway = L1ERC20Gateway( + address( + new TransparentUpgradeableProxy( + address(standardGatewayTemplate), + proxyAdmin, + bytes("") + ) + ) + ); + + standardGateway.initialize( + _computeExpectedL2StandardGatewayAddress(), + router, + inbox, + keccak256(type(ClonableBeaconProxy).creationCode), + expectedL2BeaconProxyFactoryAddress + ); + + return address(standardGateway); + } + + function _deployL1CustomGateway( + address proxyAdmin, + address router, + address inbox, + address owner + ) internal returns (address) { + L1CustomGateway customGateway = L1CustomGateway( + address( + new TransparentUpgradeableProxy( + address(customGatewayTemplate), + proxyAdmin, + bytes("") + ) + ) + ); + + customGateway.initialize( + _computeExpectedL2CustomGatewayAddress(), address(router), - address(standardGateway), - address(customGateway), inbox, - maxSubmissionCost, - maxGas, - gasPriceBid + owner ); + + return address(customGateway); } function _deployL2Factory( @@ -133,12 +192,12 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid - ) internal returns (uint256) { + ) internal { // encode L2 factory bytecode bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - uint256 ticketID = IInbox(inbox).createRetryableTicket{ value: value }( + IInbox(inbox).createRetryableTicket{ value: value }( address(0), 0, maxSubmissionCost, @@ -148,8 +207,6 @@ contract L1AtomicTokenBridgeCreator is Ownable { gasPriceBid, deploymentData ); - - return ticketID; } function _deployL2Contracts( @@ -184,58 +241,6 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); } - function _deployL1StandardGateway( - address proxyAdmin, - address router, - address inbox - ) internal returns (L1ERC20Gateway) { - L1ERC20Gateway standardGateway = L1ERC20Gateway( - address( - new TransparentUpgradeableProxy( - address(standardGatewayTemplate), - proxyAdmin, - bytes("") - ) - ) - ); - - standardGateway.initialize( - _computeExpectedL2StandardGatewayAddress(), - router, - inbox, - keccak256(type(ClonableBeaconProxy).creationCode), - expectedL2BeaconProxyFactoryAddress - ); - - return standardGateway; - } - - function _deployL1CustomGateway( - address proxyAdmin, - address router, - address inbox, - address owner - ) internal returns (L1CustomGateway) { - L1CustomGateway customGateway = L1CustomGateway( - address( - new TransparentUpgradeableProxy( - address(customGatewayTemplate), - proxyAdmin, - bytes("") - ) - ) - ); - - customGateway.initialize( - _computeExpectedL2CustomGatewayAddress(), - address(router), - inbox, - owner - ); - - return customGateway; - } - /** * @notice Generate a creation code that results on a contract with `_code` as bytecode * @param code The returning value of the resulting `creationCode` diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index e20305228d..4a32b50e2a 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -1,4 +1,4 @@ -import { Signer, Wallet, ethers } from 'ethers' +import { BigNumber, Signer, Wallet, ethers } from 'ethers' import { L1CustomGateway__factory, L1ERC20Gateway__factory, @@ -13,6 +13,7 @@ import { import { JsonRpcProvider } from '@ethersproject/providers' import { L1Network, + L1ToL2MessageGasEstimator, L1ToL2MessageStatus, L1TransactionReceipt, L2Network, @@ -23,6 +24,7 @@ import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/ import * as fs from 'fs' import { exit } from 'process' import { execSync } from 'child_process' +const { getBaseFee } = require('@arbitrum/sdk/dist/lib/utils/lib') export const setupTokenBridge = async ( l1Deployer: Signer, @@ -62,6 +64,7 @@ export const setupTokenBridge = async ( // prerequisite - deploy L1 creator and set templates const l1TokenBridgeCreator = await deployL1TokenBridgeCreator(l1Deployer) + console.log('L1TokenBridgeCreator', l1TokenBridgeCreator.address) // create token bridge const deployedContracts = await createTokenBridge( @@ -105,7 +108,7 @@ export const setupTokenBridge = async ( } /** - * Use already deployed L1TokenBridgeCreator to create and token bridge contracts. + * Use already deployed L1TokenBridgeCreator to create and init token bridge contracts. * * @param l1Signer * @param l2Signer @@ -118,24 +121,67 @@ export const createTokenBridge = async ( l1TokenBridgeCreator: L1AtomicTokenBridgeCreator, inboxAddress: string ) => { - // create token bridge - const maxSubmissionCost = ethers.utils.parseEther('0.1') - const maxGas = 10000000 - const gasPriceBid = ethers.utils.parseUnits('0.5', 'gwei') - const value = gasPriceBid.mul(maxGas).add(maxSubmissionCost).mul(5) + const deployerAddress = await l1Signer.getAddress() + const gasPrice = await l2Signer.provider!.getGasPrice() + + //// run retryable estimate for deploying L2 factory + const l1ToL2MsgGasEstimate = new L1ToL2MessageGasEstimator(l2Signer.provider!) + const deployFactoryGasParams = await l1ToL2MsgGasEstimate.estimateAll( + { + from: l1TokenBridgeCreator.address, + to: ethers.constants.AddressZero, + l2CallValue: BigNumber.from(0), + excessFeeRefundAddress: deployerAddress, + callValueRefundAddress: deployerAddress, + data: L2AtomicTokenBridgeFactory__factory.bytecode, + }, + await getBaseFee(l1Signer.provider!), + l1Signer.provider! + ) + + //// run retryable estimate for deploying L2 contracts + //// we do this estimate using L2 factory template on L1 because on L2 factory does not yet exist + const l2FactoryTemplate = L2AtomicTokenBridgeFactory__factory.connect( + await l1TokenBridgeCreator.l2TokenBridgeFactoryTemplate(), + l1Signer + ) + const gasEstimateToDeployContracts = + await l2FactoryTemplate.estimateGas.deployL2Contracts( + L2GatewayRouter__factory.bytecode, + L2ERC20Gateway__factory.bytecode, + L2CustomGateway__factory.bytecode, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address + ) + const maxGasForContracts = gasEstimateToDeployContracts.mul(2) + const maxSubmissionCostForContracts = + deployFactoryGasParams.maxSubmissionCost.mul(5) + + let retryableValue = deployFactoryGasParams.maxSubmissionCost.add( + deployFactoryGasParams.gasLimit.mul(gasPrice) + ) + retryableValue = retryableValue.add( + maxSubmissionCostForContracts.add(maxGasForContracts.mul(gasPrice)) + ) + + /// do it - create token bridge const owner = await l1Signer.getAddress() const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( inboxAddress, owner, - maxSubmissionCost, - maxGas, - gasPriceBid, - { value: value } + deployFactoryGasParams.maxSubmissionCost, + deployFactoryGasParams.gasLimit, + maxSubmissionCostForContracts, + maxGasForContracts, + gasPrice, + { value: retryableValue } ) ).wait() - /// wait for retryable execution + /// wait for execution of both tickets const l1TxReceipt = new L1TransactionReceipt(receipt) const messages = await l1TxReceipt.getL1ToL2Messages(l2Signer) const messageResults = await Promise.all( @@ -223,7 +269,6 @@ const deployL1TokenBridgeCreator = async (l1Signer: Signer) => { l1Signer ).deploy() await l1TokenBridgeCreator.deployed() - console.log('L1TokenBridgeCreator', l1TokenBridgeCreator.address) /// deploy logic contracts const routerTemplate = await new L1GatewayRouter__factory(l1Signer).deploy() diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index ceae4426d0..68a978a2b7 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -161,10 +161,12 @@ async function checkL1StandardGatewayInitialization( ) expect((await l1ERC20Gateway.l2BeaconProxyFactory()).toLowerCase()).to.be.eq( - await L2ERC20Gateway__factory.connect( - await l1ERC20Gateway.counterpartGateway(), - _l2Provider - ).beaconProxyFactory() + ( + await L2ERC20Gateway__factory.connect( + await l1ERC20Gateway.counterpartGateway(), + _l2Provider + ).beaconProxyFactory() + ).toLowerCase() ) expect((await l1ERC20Gateway.cloneableProxyHash()).toLowerCase()).to.be.eq( @@ -254,10 +256,12 @@ async function checkL2StandardGatewayInitialization( ) expect((await l2ERC20Gateway.beaconProxyFactory()).toLowerCase()).to.be.eq( - await L1ERC20Gateway__factory.connect( - await l2ERC20Gateway.counterpartGateway(), - _l1Provider - ).l2BeaconProxyFactory() + ( + await L1ERC20Gateway__factory.connect( + await l2ERC20Gateway.counterpartGateway(), + _l1Provider + ).l2BeaconProxyFactory() + ).toLowerCase() ) expect((await l2ERC20Gateway.cloneableProxyHash()).toLowerCase()).to.be.eq( From 2ddc38a66e5710d97a367baa22f3bdd7b172324c Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Jul 2023 10:26:34 +0200 Subject: [PATCH 093/163] deployL2Contracts can only be executed once --- .../tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol | 5 ++++- .../tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index f0430ccdf3..9d870be41c 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import { L2GatewayRouter } from "./gateway/L2GatewayRouter.sol"; import { L2ERC20Gateway } from "./gateway/L2ERC20Gateway.sol"; @@ -11,6 +11,8 @@ import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; +error L2AtomicTokenBridgeFactory_AlreadyInitialized(); + contract L2AtomicTokenBridgeFactory { address public proxyAdmin; L2GatewayRouter public router; @@ -26,6 +28,7 @@ contract L2AtomicTokenBridgeFactory { address l1CustomGateway, address l2StandardGatewayExpectedAddress ) external { + if (address(router) != address(0)) revert L2AtomicTokenBridgeFactory_AlreadyInitialized(); _deployRouter(routerCreationCode, l1Router, l2StandardGatewayExpectedAddress); _deployStandardGateway(standardGatewayCreationCode, l1StandardGateway); _deployCustomGateway(customGatewayCreationCode, l1CustomGateway); diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 8f39de26f5..e39b0d2579 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.0; +pragma solidity ^0.8.4; import { L1GatewayRouter } from "./gateway/L1GatewayRouter.sol"; import { L1ERC20Gateway } from "./gateway/L1ERC20Gateway.sol"; From 2e51766c3e51e3d6704cae3fbc9f5d46b1b380f5 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Jul 2023 13:14:13 +0200 Subject: [PATCH 094/163] Use L1Factory's address as part of salt calculation --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 94 +++++++---- .../ethereum/L1AtomicTokenBridgeCreator.sol | 154 ++++++++++-------- package.json | 7 +- .../atomicTokenBridgeDeployer.ts | 65 ++++---- test-e2e/tokenBridgeDeploymentTest.ts | 134 ++++++++++----- 5 files changed, 272 insertions(+), 182 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 9d870be41c..cf7a9ceec5 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -11,14 +11,7 @@ import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; -error L2AtomicTokenBridgeFactory_AlreadyInitialized(); - contract L2AtomicTokenBridgeFactory { - address public proxyAdmin; - L2GatewayRouter public router; - L2ERC20Gateway public standardGateway; - L2CustomGateway public customGateway; - function deployL2Contracts( bytes memory routerCreationCode, bytes memory standardGatewayCreationCode, @@ -26,27 +19,40 @@ contract L2AtomicTokenBridgeFactory { address l1Router, address l1StandardGateway, address l1CustomGateway, - address l2StandardGatewayExpectedAddress + address l2StandardGatewayExpectedAddress, + address proxyAdminOwner ) external { - if (address(router) != address(0)) revert L2AtomicTokenBridgeFactory_AlreadyInitialized(); - _deployRouter(routerCreationCode, l1Router, l2StandardGatewayExpectedAddress); - _deployStandardGateway(standardGatewayCreationCode, l1StandardGateway); - _deployCustomGateway(customGatewayCreationCode, l1CustomGateway); + // create proxyAdmin which will be used for all contracts + address proxyAdmin = address(new ProxyAdmin{ salt: _getSaltFrom(L2Salts.PROXY_ADMIN) }()); + + address router = _deployRouter( + routerCreationCode, + l1Router, + l2StandardGatewayExpectedAddress, + proxyAdmin + ); + _deployStandardGateway(standardGatewayCreationCode, l1StandardGateway, router, proxyAdmin); + _deployCustomGateway(customGatewayCreationCode, l1CustomGateway, router, proxyAdmin); + + // transfer ownership to L1Creator's msg.sender + ProxyAdmin(proxyAdmin).transferOwnership(proxyAdminOwner); } function _deployRouter( bytes memory creationCode, address l1Router, - address l2StandardGatewayExpectedAddress - ) internal { - // first create proxyAdmin which will be used for all contracts - proxyAdmin = address(new ProxyAdmin{ salt: L2Salts.PROXY_ADMIN }()); - + address l2StandardGatewayExpectedAddress, + address proxyAdmin + ) internal returns (address) { // create logic and proxy - address routerLogicAddress = Create2.deploy(0, L2Salts.ROUTER_LOGIC, creationCode); - router = L2GatewayRouter( + address routerLogicAddress = Create2.deploy( + 0, + _getSaltFrom(L2Salts.ROUTER_LOGIC), + creationCode + ); + L2GatewayRouter router = L2GatewayRouter( address( - new TransparentUpgradeableProxy{ salt: L2Salts.ROUTER }( + new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.ROUTER) }( routerLogicAddress, proxyAdmin, bytes("") @@ -56,18 +62,25 @@ contract L2AtomicTokenBridgeFactory { // init router.initialize(l1Router, l2StandardGatewayExpectedAddress); + + return address(router); } - function _deployStandardGateway(bytes memory creationCode, address l1StandardGateway) internal { + function _deployStandardGateway( + bytes memory creationCode, + address l1StandardGateway, + address router, + address proxyAdmin + ) internal { // create logic and proxy address standardGatewayLogicAddress = Create2.deploy( 0, - L2Salts.STANDARD_GATEWAY_LOGIC, + _getSaltFrom(L2Salts.STANDARD_GATEWAY_LOGIC), creationCode ); - standardGateway = L2ERC20Gateway( + L2ERC20Gateway standardGateway = L2ERC20Gateway( address( - new TransparentUpgradeableProxy{ salt: L2Salts.STANDARD_GATEWAY }( + new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.STANDARD_GATEWAY) }( standardGatewayLogicAddress, proxyAdmin, bytes("") @@ -76,30 +89,37 @@ contract L2AtomicTokenBridgeFactory { ); // create beacon - StandardArbERC20 standardArbERC20 = new StandardArbERC20{ salt: L2Salts.STANDARD_ERC20 }(); - UpgradeableBeacon beacon = new UpgradeableBeacon{ salt: L2Salts.UPGRADEABLE_BEACON }( - address(standardArbERC20) - ); + StandardArbERC20 standardArbERC20 = new StandardArbERC20{ + salt: _getSaltFrom(L2Salts.STANDARD_ERC20) + }(); + UpgradeableBeacon beacon = new UpgradeableBeacon{ + salt: _getSaltFrom(L2Salts.UPGRADEABLE_BEACON) + }(address(standardArbERC20)); BeaconProxyFactory beaconProxyFactory = new BeaconProxyFactory{ - salt: L2Salts.BEACON_PROXY_FACTORY + salt: _getSaltFrom(L2Salts.BEACON_PROXY_FACTORY) }(); // init contracts beaconProxyFactory.initialize(address(beacon)); - standardGateway.initialize(l1StandardGateway, address(router), address(beaconProxyFactory)); + standardGateway.initialize(l1StandardGateway, router, address(beaconProxyFactory)); } - function _deployCustomGateway(bytes memory creationCode, address l1CustomGateway) internal { + function _deployCustomGateway( + bytes memory creationCode, + address l1CustomGateway, + address router, + address proxyAdmin + ) internal { address customGatewayLogicAddress = Create2.deploy( 0, - L2Salts.CUSTOM_GATEWAY_LOGIC, + _getSaltFrom(L2Salts.CUSTOM_GATEWAY_LOGIC), creationCode ); // create logic and proxy - customGateway = L2CustomGateway( + L2CustomGateway customGateway = L2CustomGateway( address( - new TransparentUpgradeableProxy{ salt: L2Salts.CUSTOM_GATEWAY }( + new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.CUSTOM_GATEWAY) }( customGatewayLogicAddress, proxyAdmin, bytes("") @@ -108,7 +128,11 @@ contract L2AtomicTokenBridgeFactory { ); // init - customGateway.initialize(l1CustomGateway, address(router)); + customGateway.initialize(l1CustomGateway, router); + } + + function _getSaltFrom(bytes32 prefix) internal view returns (bytes32) { + return keccak256(abi.encodePacked(prefix, msg.sender)); } } diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index e39b0d2579..b8b7255bc8 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -42,13 +42,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); expectedL2ProxyAdminAddress = Create2.computeAddress( - L2Salts.PROXY_ADMIN, + _getSaltFrom(L2Salts.PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), expectedL2FactoryAddress ); expectedL2BeaconProxyFactoryAddress = Create2.computeAddress( - L2Salts.BEACON_PROXY_FACTORY, + _getSaltFrom(L2Salts.BEACON_PROXY_FACTORY), keccak256(type(BeaconProxyFactory).creationCode), expectedL2FactoryAddress ); @@ -77,13 +77,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { function createTokenBridge( address inbox, - address owner, uint256 maxSubmissionCostForFactory, uint256 maxGasForFactory, uint256 maxSubmissionCostForContracts, uint256 maxGasForContracts, uint256 gasPriceBid ) external payable { + address owner = msg.sender; (address router, address standardGateway, address customGateway) = _deployL1Contracts( inbox, owner @@ -122,10 +122,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { owner, address(standardGateway), address(0), - _computeExpectedL2RouterAddress(), + computeExpectedL2RouterAddress(), inbox ); + // transfer ownership to owner + ProxyAdmin(proxyAdmin).transferOwnership(owner); + // emit it emit OrbitTokenBridgeCreated( address(router), @@ -151,7 +154,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); standardGateway.initialize( - _computeExpectedL2StandardGatewayAddress(), + computeExpectedL2StandardGatewayAddress(), router, inbox, keccak256(type(ClonableBeaconProxy).creationCode), @@ -178,7 +181,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); customGateway.initialize( - _computeExpectedL2CustomGatewayAddress(), + computeExpectedL2CustomGatewayAddress(), address(router), inbox, owner @@ -218,6 +221,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 maxGas, uint256 gasPriceBid ) internal { + address proxyAdminOwner = msg.sender; bytes memory data = abi.encodeWithSelector( L2AtomicTokenBridgeFactory.deployL2Contracts.selector, _creationCodeFor(l2RouterTemplate.code), @@ -226,7 +230,8 @@ contract L1AtomicTokenBridgeCreator is Ownable { l1Router, l1StandardGateway, l1CustomGateway, - _computeExpectedL2StandardGatewayAddress() + computeExpectedL2StandardGatewayAddress(), + proxyAdminOwner ); IInbox(inbox).createRetryableTicket{ value: maxSubmissionCost + maxGas * gasPriceBid }( @@ -241,8 +246,75 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); } + function computeExpectedL2RouterAddress() public view returns (address) { + address expectedL2RouterLogic = Create2.computeAddress( + _getSaltFrom(L2Salts.ROUTER_LOGIC), + keccak256(_creationCodeFor(l2RouterTemplate.code)), + expectedL2FactoryAddress + ); + + return + Create2.computeAddress( + _getSaltFrom(L2Salts.ROUTER), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(expectedL2RouterLogic, expectedL2ProxyAdminAddress, bytes("")) + ) + ), + expectedL2FactoryAddress + ); + } + + function computeExpectedL2StandardGatewayAddress() public view returns (address) { + address expectedL2StandardGatewayLogic = Create2.computeAddress( + _getSaltFrom(L2Salts.STANDARD_GATEWAY_LOGIC), + keccak256(_creationCodeFor(l2StandardGatewayTemplate.code)), + expectedL2FactoryAddress + ); + return + Create2.computeAddress( + _getSaltFrom(L2Salts.STANDARD_GATEWAY), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode( + expectedL2StandardGatewayLogic, + expectedL2ProxyAdminAddress, + bytes("") + ) + ) + ), + expectedL2FactoryAddress + ); + } + + function computeExpectedL2CustomGatewayAddress() public view returns (address) { + address expectedL2CustomGatewayLogic = Create2.computeAddress( + _getSaltFrom(L2Salts.CUSTOM_GATEWAY_LOGIC), + keccak256(_creationCodeFor(l2CustomGatewayTemplate.code)), + expectedL2FactoryAddress + ); + + return + Create2.computeAddress( + _getSaltFrom(L2Salts.CUSTOM_GATEWAY), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode( + expectedL2CustomGatewayLogic, + expectedL2ProxyAdminAddress, + bytes("") + ) + ) + ), + expectedL2FactoryAddress + ); + } + /** - * @notice Generate a creation code that results on a contract with `_code` as bytecode + * @notice Generate a creation code that results on a contract with `code` as bytecode * @param code The returning value of the resulting `creationCode` * @return creationCode (constructor) for new contract */ @@ -303,70 +375,8 @@ contract L1AtomicTokenBridgeCreator is Ownable { return address(uint160(uint256(keccak256(data)))); } - function _computeExpectedL2RouterAddress() internal view returns (address) { - address expectedL2RouterLogic = Create2.computeAddress( - L2Salts.ROUTER_LOGIC, - keccak256(_creationCodeFor(l2RouterTemplate.code)), - expectedL2FactoryAddress - ); - + function _getSaltFrom(bytes32 prefix) internal view returns (bytes32) { return - Create2.computeAddress( - L2Salts.ROUTER, - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2RouterLogic, expectedL2ProxyAdminAddress, bytes("")) - ) - ), - expectedL2FactoryAddress - ); - } - - function _computeExpectedL2StandardGatewayAddress() internal view returns (address) { - address expectedL2StandardGatewayLogic = Create2.computeAddress( - L2Salts.STANDARD_GATEWAY_LOGIC, - keccak256(_creationCodeFor(l2StandardGatewayTemplate.code)), - expectedL2FactoryAddress - ); - return - Create2.computeAddress( - L2Salts.STANDARD_GATEWAY, - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode( - expectedL2StandardGatewayLogic, - expectedL2ProxyAdminAddress, - bytes("") - ) - ) - ), - expectedL2FactoryAddress - ); - } - - function _computeExpectedL2CustomGatewayAddress() internal view returns (address) { - address expectedL2CustomGatewayLogic = Create2.computeAddress( - L2Salts.CUSTOM_GATEWAY_LOGIC, - keccak256(_creationCodeFor(l2CustomGatewayTemplate.code)), - expectedL2FactoryAddress - ); - - return - Create2.computeAddress( - L2Salts.CUSTOM_GATEWAY, - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode( - expectedL2CustomGatewayLogic, - expectedL2ProxyAdminAddress, - bytes("") - ) - ) - ), - expectedL2FactoryAddress - ); + keccak256(abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(this)))); } } diff --git a/package.json b/package.json index 5a0d0bdc63..4848db18c2 100644 --- a/package.json +++ b/package.json @@ -18,9 +18,10 @@ "test:l1": "hardhat test test/*.l1.ts", "test:l2": "hardhat test test/*.l2.ts", "test:storage": "./scripts/storage_layout_test.bash", - "test:deploy:tokenbridge": "ts-node ./scripts/local-deployment/tokenBridgeDeployer.ts", - "test:deploy:tokenbridge:factories": "ts-node ./scripts/local-deployment/factoryTokenBridgeDeployer.ts", - "test:deploy:tokenbridge:atomic": "ts-node ./scripts/local-deployment/atomicTokenBridgeDeployer.ts", + "deploy:tokenbridge:script": "ts-node ./scripts/local-deployment/tokenBridgeDeployer.ts", + "deploy:tokenbridge:factories": "ts-node ./scripts/local-deployment/factoryTokenBridgeDeployer.ts", + "deploy:tokenbridge:atomic": "ts-node ./scripts/local-deployment/atomicTokenBridgeDeployer.ts", + "test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.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", diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 4a32b50e2a..4eebabf5f5 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -24,9 +24,22 @@ import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/ import * as fs from 'fs' import { exit } from 'process' import { execSync } from 'child_process' -const { getBaseFee } = require('@arbitrum/sdk/dist/lib/utils/lib') +import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' -export const setupTokenBridge = async ( +/** + * Steps: + * - read network info from local container and register networks + * - deploy L1 bridge creator and set templates + * - do single TX deployment of token bridge + * - populate network objects with new addresses and return it + * + * @param l1Deployer + * @param l2Deployer + * @param l1Url + * @param l2Url + * @returns + */ +export const setupTokenBridgeInLocalEnv = async ( l1Deployer: Signer, l2Deployer: Signer, l1Url: string, @@ -95,12 +108,6 @@ export const setupTokenBridge = async ( }, } - // can't re-add - // addCustomNetwork({ - // customL1Network: l1Network, - // customL2Network: l2Network, - // }) - return { l1Network, l2Network, @@ -153,6 +160,7 @@ export const createTokenBridge = async ( ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address ) const maxGasForContracts = gasEstimateToDeployContracts.mul(2) @@ -167,11 +175,9 @@ export const createTokenBridge = async ( ) /// do it - create token bridge - const owner = await l1Signer.getAddress() const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( inboxAddress, - owner, deployFactoryGasParams.maxSubmissionCost, deployFactoryGasParams.gasLimit, maxSubmissionCostForContracts, @@ -227,14 +233,15 @@ export const createTokenBridge = async ( )[0].args /// pick up L2 contracts from L1 factory contract - const l2Router = await l2AtomicTokenBridgeFactory.router() + const l2Router = await l1TokenBridgeCreator.computeExpectedL2RouterAddress() const l2StandardGateway = L2ERC20Gateway__factory.connect( - await l2AtomicTokenBridgeFactory.standardGateway(), + await l1TokenBridgeCreator.computeExpectedL2StandardGatewayAddress(), l2Signer ) const beaconProxyFactory = await l2StandardGateway.beaconProxyFactory() - const l2CustomGateway = await l2AtomicTokenBridgeFactory.customGateway() - const l2ProxyAdmin = await l2AtomicTokenBridgeFactory.proxyAdmin() + const l2CustomGateway = + await l1TokenBridgeCreator.computeExpectedL2CustomGatewayAddress() + const l2ProxyAdmin = await l1TokenBridgeCreator.expectedL2ProxyAdminAddress() return { l1Router, @@ -249,20 +256,6 @@ export const createTokenBridge = async ( } } -const getParsedLogs = ( - logs: ethers.providers.Log[], - iface: ethers.utils.Interface, - eventName: string -) => { - const eventFragment = iface.getEvent(eventName) - const parsedLogs = logs - .filter( - (curr: any) => curr.topics[0] === iface.getEventTopic(eventFragment) - ) - .map((curr: any) => iface.parseLog(curr)) - return parsedLogs -} - const deployL1TokenBridgeCreator = async (l1Signer: Signer) => { /// deploy factory const l1TokenBridgeCreator = await new L1AtomicTokenBridgeCreator__factory( @@ -407,6 +400,20 @@ export const getSigner = (provider: JsonRpcProvider, key?: string) => { else return provider.getSigner(0) } +const getParsedLogs = ( + logs: ethers.providers.Log[], + iface: ethers.utils.Interface, + eventName: string +) => { + const eventFragment = iface.getEvent(eventName) + const parsedLogs = logs + .filter( + (curr: any) => curr.topics[0] === iface.getEventTopic(eventFragment) + ) + .map((curr: any) => iface.parseLog(curr)) + return parsedLogs +} + export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)) } @@ -429,7 +436,7 @@ async function main() { l2Provider ) - const { l1Network, l2Network } = await setupTokenBridge( + const { l1Network, l2Network } = await setupTokenBridgeInLocalEnv( l1DeployerWallet, l2DeployerWallet, config.ethUrl, diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index 68a978a2b7..e2d5540b64 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -18,6 +18,8 @@ import { L2GatewayRouter__factory, L2WethGateway, L2WethGateway__factory, + ProxyAdmin, + ProxyAdmin__factory, } from '../build/types' import path from 'path' import fs from 'fs' @@ -41,9 +43,6 @@ let _l1Provider: JsonRpcProvider let _l2Provider: JsonRpcProvider describe('tokenBridge', () => { - // configure token bridge - before(async function () {}) - it('should have deployed and initialized token bridge contracts', async function () { const { l1Network, l1Provider, l2Network, l2Provider } = await getProvidersAndSetupNetworks({ @@ -60,76 +59,97 @@ describe('tokenBridge', () => { //// L1 checks - checkL1RouterInitialization( + await checkL1RouterInitialization( L1GatewayRouter__factory.connect( _l2Network.tokenBridge.l1GatewayRouter, l1Provider ) ) - checkL1StandardGatewayInitialization( + await checkL1StandardGatewayInitialization( L1ERC20Gateway__factory.connect( _l2Network.tokenBridge.l1ERC20Gateway, l1Provider ) ) - checkL1CustomGatewayInitialization( + await checkL1CustomGatewayInitialization( L1CustomGateway__factory.connect( _l2Network.tokenBridge.l1CustomGateway, l1Provider ) ) - checkL1WethGatewayInitialization( - L1WethGateway__factory.connect( - _l2Network.tokenBridge.l1WethGateway, - l1Provider - ) - ) + // await checkL1WethGatewayInitialization( + // L1WethGateway__factory.connect( + // _l2Network.tokenBridge.l1WethGateway, + // l1Provider + // ) + // ) //// L2 checks - checkL2RouterInitialization( + await checkL2RouterInitialization( L2GatewayRouter__factory.connect( _l2Network.tokenBridge.l2GatewayRouter, l2Provider ) ) - checkL2StandardGatewayInitialization( + await checkL2StandardGatewayInitialization( L2ERC20Gateway__factory.connect( _l2Network.tokenBridge.l2ERC20Gateway, l2Provider ) ) - checkL2CustomGatewayInitialization( + await checkL2CustomGatewayInitialization( L2CustomGateway__factory.connect( _l2Network.tokenBridge.l2CustomGateway, l2Provider ) ) - checkL2WethGatewayInitialization( - L2WethGateway__factory.connect( - _l2Network.tokenBridge.l2WethGateway, + await checkOwnership( + ProxyAdmin__factory.connect( + _l2Network.tokenBridge.l1ProxyAdmin, + l1Provider + ), + ProxyAdmin__factory.connect( + _l2Network.tokenBridge.l2ProxyAdmin, l2Provider + ), + L1GatewayRouter__factory.connect( + _l2Network.tokenBridge.l1GatewayRouter, + l1Provider + ), + L1CustomGateway__factory.connect( + _l2Network.tokenBridge.l1CustomGateway, + l1Provider ) ) + + // await checkL2WethGatewayInitialization( + // L2WethGateway__factory.connect( + // _l2Network.tokenBridge.l2WethGateway, + // l2Provider + // ) + // ) }) }) //// L1 contracts async function checkL1RouterInitialization(l1Router: L1GatewayRouter) { + console.log('checkL1RouterInitialization') + expect((await l1Router.defaultGateway()).toLowerCase()).to.be.eq( _l2Network.tokenBridge.l1ERC20Gateway.toLowerCase() ) // TODO - generic way to check owner // expect((await l1Router.owner()).toLowerCase()).to.be.eq( - // (await l1Signer.getAddress(),º.toLowerCase() + // (await l1Signer.getAddress().toLowerCase() // ) expect((await l1Router.inbox()).toLowerCase()).to.be.eq( @@ -148,18 +168,17 @@ async function checkL1RouterInitialization(l1Router: L1GatewayRouter) { async function checkL1StandardGatewayInitialization( l1ERC20Gateway: L1ERC20Gateway ) { + console.log('checkL1StandardGatewayInitialization') + expect((await l1ERC20Gateway.counterpartGateway()).toLowerCase()).to.be.eq( _l2Network.tokenBridge.l2ERC20Gateway.toLowerCase() ) - expect((await l1ERC20Gateway.router()).toLowerCase()).to.be.eq( _l2Network.tokenBridge.l1GatewayRouter.toLowerCase() ) - expect((await l1ERC20Gateway.inbox()).toLowerCase()).to.be.eq( _l2Network.ethBridge.inbox.toLowerCase() ) - expect((await l1ERC20Gateway.l2BeaconProxyFactory()).toLowerCase()).to.be.eq( ( await L2ERC20Gateway__factory.connect( @@ -168,16 +187,14 @@ async function checkL1StandardGatewayInitialization( ).beaconProxyFactory() ).toLowerCase() ) - expect((await l1ERC20Gateway.cloneableProxyHash()).toLowerCase()).to.be.eq( ( await BeaconProxyFactory__factory.connect( - await l1ERC20Gateway.cloneableProxyHash(), + await l1ERC20Gateway.l2BeaconProxyFactory(), _l2Provider ).cloneableProxyHash() ).toLowerCase() ) - expect((await l1ERC20Gateway.whitelist()).toLowerCase()).to.be.eq( ethers.constants.AddressZero ) @@ -186,6 +203,8 @@ async function checkL1StandardGatewayInitialization( async function checkL1CustomGatewayInitialization( l1CustomGateway: L1CustomGateway ) { + console.log('checkL1CustomGatewayInitialization') + expect((await l1CustomGateway.counterpartGateway()).toLowerCase()).to.be.eq( _l2Network.tokenBridge.l2CustomGateway.toLowerCase() ) @@ -207,6 +226,8 @@ async function checkL1CustomGatewayInitialization( } async function checkL1WethGatewayInitialization(l1WethGateway: L1WethGateway) { + console.log('checkL1WethGatewayInitialization') + expect((await l1WethGateway.counterpartGateway()).toLowerCase()).to.be.eq( _l2Network.tokenBridge.l2WethGateway.toLowerCase() ) @@ -231,6 +252,8 @@ async function checkL1WethGatewayInitialization(l1WethGateway: L1WethGateway) { //// L2 contracts async function checkL2RouterInitialization(l2Router: L2GatewayRouter) { + console.log('checkL2RouterInitialization') + expect((await l2Router.defaultGateway()).toLowerCase()).to.be.eq( _l2Network.tokenBridge.l2ERC20Gateway.toLowerCase() ) @@ -247,6 +270,8 @@ async function checkL2RouterInitialization(l2Router: L2GatewayRouter) { async function checkL2StandardGatewayInitialization( l2ERC20Gateway: L2ERC20Gateway ) { + console.log('checkL2StandardGatewayInitialization') + expect((await l2ERC20Gateway.counterpartGateway()).toLowerCase()).to.be.eq( _l2Network.tokenBridge.l1ERC20Gateway.toLowerCase() ) @@ -277,6 +302,8 @@ async function checkL2StandardGatewayInitialization( async function checkL2CustomGatewayInitialization( l2CustomGateway: L2CustomGateway ) { + console.log('checkL2CustomGatewayInitialization') + expect((await l2CustomGateway.counterpartGateway()).toLowerCase()).to.be.eq( _l2Network.tokenBridge.l1CustomGateway.toLowerCase() ) @@ -286,6 +313,45 @@ async function checkL2CustomGatewayInitialization( ) } +async function checkL2WethGatewayInitialization(l2WethGateway: L2WethGateway) { + console.log('checkL2WethGatewayInitialization') + + expect((await l2WethGateway.counterpartGateway()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1WethGateway.toLowerCase() + ) + + expect((await l2WethGateway.router()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() + ) + + expect((await l2WethGateway.l1Weth()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l1Weth.toLowerCase() + ) + + expect((await l2WethGateway.l2Weth()).toLowerCase()).to.be.eq( + _l2Network.tokenBridge.l2Weth.toLowerCase() + ) +} + +async function checkOwnership( + l1ProxyAdmin: ProxyAdmin, + l2ProxyAdmin: ProxyAdmin, + l1Router: L1GatewayRouter, + l1CustomGateway: L1CustomGateway +) { + console.log('checkL2ProxyAdminInitialization') + + const l1Owner = await l1ProxyAdmin.owner() + + expect(l1Owner.toLowerCase()).to.be.eq( + (await l2ProxyAdmin.owner()).toLowerCase() + ) + expect(l1Owner.toLowerCase()).to.be.eq((await l1Router.owner()).toLowerCase()) + expect(l1Owner.toLowerCase()).to.be.eq( + (await l1CustomGateway.owner()).toLowerCase() + ) +} + export const getProvidersAndSetupNetworks = async (setupConfig: { l1Url: string l2Url: string @@ -340,21 +406,3 @@ export const getProvidersAndSetupNetworks = async (setupConfig: { } } } - -async function checkL2WethGatewayInitialization(l2WethGateway: L2WethGateway) { - expect((await l2WethGateway.counterpartGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1WethGateway.toLowerCase() - ) - - expect((await l2WethGateway.router()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() - ) - - expect((await l2WethGateway.l1Weth()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1Weth.toLowerCase() - ) - - expect((await l2WethGateway.l2Weth()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2Weth.toLowerCase() - ) -} From bd7c8c995840cc50ff2bbab300cf2caf42b99361 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Jul 2023 13:36:39 +0200 Subject: [PATCH 095/163] Formatting, add some docs --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 53 ++-- .../arbitrum/L2TokenBridgeFactory.sol | 40 +-- .../ethereum/L1AtomicTokenBridgeCreator.sol | 269 +++++++----------- .../ethereum/L1TokenBridgeCreator.sol | 48 +--- 4 files changed, 149 insertions(+), 261 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index cf7a9ceec5..420900b929 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -1,16 +1,21 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.4; -import { L2GatewayRouter } from "./gateway/L2GatewayRouter.sol"; -import { L2ERC20Gateway } from "./gateway/L2ERC20Gateway.sol"; -import { L2CustomGateway } from "./gateway/L2CustomGateway.sol"; -import { StandardArbERC20 } from "./StandardArbERC20.sol"; -import { BeaconProxyFactory } from "../libraries/ClonableBeaconProxy.sol"; -import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; -import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; +import {L2GatewayRouter} from "./gateway/L2GatewayRouter.sol"; +import {L2ERC20Gateway} from "./gateway/L2ERC20Gateway.sol"; +import {L2CustomGateway} from "./gateway/L2CustomGateway.sol"; +import {StandardArbERC20} from "./StandardArbERC20.sol"; +import {BeaconProxyFactory} from "../libraries/ClonableBeaconProxy.sol"; +import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; +/** + * @title Layer2 token bridge creator + * @notice This contract is used to deploy token bridge on L2 chain. + * @dev L1AtomicTokenBridgeCreator shall call `deployL2Contracts` using retryable and that will result in deployment of canonical token bridge contracts. + */ contract L2AtomicTokenBridgeFactory { function deployL2Contracts( bytes memory routerCreationCode, @@ -25,12 +30,8 @@ contract L2AtomicTokenBridgeFactory { // create proxyAdmin which will be used for all contracts address proxyAdmin = address(new ProxyAdmin{ salt: _getSaltFrom(L2Salts.PROXY_ADMIN) }()); - address router = _deployRouter( - routerCreationCode, - l1Router, - l2StandardGatewayExpectedAddress, - proxyAdmin - ); + // deploy router/gateways + address router = _deployRouter(routerCreationCode, l1Router, l2StandardGatewayExpectedAddress, proxyAdmin); _deployStandardGateway(standardGatewayCreationCode, l1StandardGateway, router, proxyAdmin); _deployCustomGateway(customGatewayCreationCode, l1CustomGateway, router, proxyAdmin); @@ -45,11 +46,7 @@ contract L2AtomicTokenBridgeFactory { address proxyAdmin ) internal returns (address) { // create logic and proxy - address routerLogicAddress = Create2.deploy( - 0, - _getSaltFrom(L2Salts.ROUTER_LOGIC), - creationCode - ); + address routerLogicAddress = Create2.deploy(0, _getSaltFrom(L2Salts.ROUTER_LOGIC), creationCode); L2GatewayRouter router = L2GatewayRouter( address( new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.ROUTER) }( @@ -73,11 +70,8 @@ contract L2AtomicTokenBridgeFactory { address proxyAdmin ) internal { // create logic and proxy - address standardGatewayLogicAddress = Create2.deploy( - 0, - _getSaltFrom(L2Salts.STANDARD_GATEWAY_LOGIC), - creationCode - ); + address standardGatewayLogicAddress = + Create2.deploy(0, _getSaltFrom(L2Salts.STANDARD_GATEWAY_LOGIC), creationCode); L2ERC20Gateway standardGateway = L2ERC20Gateway( address( new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.STANDARD_GATEWAY) }( @@ -110,11 +104,7 @@ contract L2AtomicTokenBridgeFactory { address router, address proxyAdmin ) internal { - address customGatewayLogicAddress = Create2.deploy( - 0, - _getSaltFrom(L2Salts.CUSTOM_GATEWAY_LOGIC), - creationCode - ); + address customGatewayLogicAddress = Create2.deploy(0, _getSaltFrom(L2Salts.CUSTOM_GATEWAY_LOGIC), creationCode); // create logic and proxy L2CustomGateway customGateway = L2CustomGateway( @@ -143,8 +133,7 @@ library L2Salts { bytes32 public constant PROXY_ADMIN = keccak256(bytes("OrbitL2ProxyAdmin")); bytes32 public constant ROUTER_LOGIC = keccak256(bytes("OrbitL2GatewayRouterLogic")); bytes32 public constant ROUTER = keccak256(bytes("OrbitL2GatewayRouterProxy")); - bytes32 public constant STANDARD_GATEWAY_LOGIC = - keccak256(bytes("OrbitL2StandardGatewayLogic")); + bytes32 public constant STANDARD_GATEWAY_LOGIC = keccak256(bytes("OrbitL2StandardGatewayLogic")); bytes32 public constant STANDARD_GATEWAY = keccak256(bytes("OrbitL2StandardGatewayProxy")); bytes32 public constant CUSTOM_GATEWAY_LOGIC = keccak256(bytes("OrbitL2CustomGatewayLogic")); bytes32 public constant CUSTOM_GATEWAY = keccak256(bytes("OrbitL2CustomGatewayProxy")); diff --git a/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol index 405a6dab0c..401557512d 100644 --- a/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol @@ -1,36 +1,26 @@ pragma solidity ^0.8.0; -import { L2GatewayRouter } from "./gateway/L2GatewayRouter.sol"; -import { L2ERC20Gateway } from "./gateway/L2ERC20Gateway.sol"; -import { L2CustomGateway } from "./gateway/L2CustomGateway.sol"; -import { StandardArbERC20 } from "./StandardArbERC20.sol"; -import { BeaconProxyFactory } from "../libraries/ClonableBeaconProxy.sol"; -import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; -import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {L2GatewayRouter} from "./gateway/L2GatewayRouter.sol"; +import {L2ERC20Gateway} from "./gateway/L2ERC20Gateway.sol"; +import {L2CustomGateway} from "./gateway/L2CustomGateway.sol"; +import {StandardArbERC20} from "./StandardArbERC20.sol"; +import {BeaconProxyFactory} from "../libraries/ClonableBeaconProxy.sol"; +import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract L2TokenBridgeFactory { event OrbitL2TokenBridgeCreated( - address router, - address standardGateway, - address customGateway, - address beaconProxyFactory, - address proxyAdmin + address router, address standardGateway, address customGateway, address beaconProxyFactory, address proxyAdmin ); constructor(address l1Router, address l1StandardGateway, address l1CustomGateway) { address proxyAdmin = address(new ProxyAdmin()); // create router/gateways - L2GatewayRouter router = L2GatewayRouter( - _deployBehindProxy(address(new L2GatewayRouter()), proxyAdmin) - ); - L2ERC20Gateway standardGateway = L2ERC20Gateway( - _deployBehindProxy(address(new L2ERC20Gateway()), proxyAdmin) - ); - L2CustomGateway customGateway = L2CustomGateway( - _deployBehindProxy(address(new L2CustomGateway()), proxyAdmin) - ); + L2GatewayRouter router = L2GatewayRouter(_deployBehindProxy(address(new L2GatewayRouter()), proxyAdmin)); + L2ERC20Gateway standardGateway = L2ERC20Gateway(_deployBehindProxy(address(new L2ERC20Gateway()), proxyAdmin)); + L2CustomGateway customGateway = L2CustomGateway(_deployBehindProxy(address(new L2CustomGateway()), proxyAdmin)); // create beacon StandardArbERC20 standardArbERC20 = new StandardArbERC20(); @@ -44,11 +34,7 @@ contract L2TokenBridgeFactory { customGateway.initialize(l1CustomGateway, address(router)); emit OrbitL2TokenBridgeCreated( - address(router), - address(standardGateway), - address(customGateway), - address(beaconProxyFactory), - proxyAdmin + address(router), address(standardGateway), address(customGateway), address(beaconProxyFactory), proxyAdmin ); } diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index b8b7255bc8..5e87f6aef2 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -1,25 +1,25 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.4; -import { L1GatewayRouter } from "./gateway/L1GatewayRouter.sol"; -import { L1ERC20Gateway } from "./gateway/L1ERC20Gateway.sol"; -import { L1CustomGateway } from "./gateway/L1CustomGateway.sol"; -import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import { L2AtomicTokenBridgeFactory, L2Salts } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { IInbox } from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; -import { AddressAliasHelper } from "../libraries/AddressAliasHelper.sol"; -import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; -import { BeaconProxyFactory, ClonableBeaconProxy } from "../libraries/ClonableBeaconProxy.sol"; - +import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol"; +import {L1ERC20Gateway} from "./gateway/L1ERC20Gateway.sol"; +import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {L2AtomicTokenBridgeFactory, L2Salts} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {IInbox} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; +import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; +import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; +import {BeaconProxyFactory, ClonableBeaconProxy} from "../libraries/ClonableBeaconProxy.sol"; + +/** + * @title Layer1 token bridge creator + * @notice This contract is used to deploy token bridge on custom L2 chains. + * @dev Throughout the contract terms L1 and L2 are used, but those can be considered as base (N) chain and child (N+1) chain + */ contract L1AtomicTokenBridgeCreator is Ownable { - event OrbitTokenBridgeCreated( - address router, - address standardGateway, - address customGateway, - address proxyAdmin - ); + event OrbitTokenBridgeCreated(address router, address standardGateway, address customGateway, address proxyAdmin); event OrbitTokenBridgeTemplatesUpdated(); L1GatewayRouter public routerTemplate; @@ -36,15 +36,10 @@ contract L1AtomicTokenBridgeCreator is Ownable { address public immutable expectedL2BeaconProxyFactoryAddress; constructor() Ownable() { - expectedL2FactoryAddress = _computeAddress( - AddressAliasHelper.applyL1ToL2Alias(address(this)), - 0 - ); + expectedL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); expectedL2ProxyAdminAddress = Create2.computeAddress( - _getSaltFrom(L2Salts.PROXY_ADMIN), - keccak256(type(ProxyAdmin).creationCode), - expectedL2FactoryAddress + _getSaltFrom(L2Salts.PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), expectedL2FactoryAddress ); expectedL2BeaconProxyFactoryAddress = Create2.computeAddress( @@ -54,6 +49,11 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); } + /** + * @notice Set addresses of L1 logic contracts and L2 contracts which are deployed on L1. + * @dev L2 contracts are deployed to L1 as bytecode placeholders - that bytecode will be part of retryable + * payload used to deploy contracts on L2 side. + */ function setTemplates( L1GatewayRouter _router, L1ERC20Gateway _standardGateway, @@ -75,6 +75,12 @@ contract L1AtomicTokenBridgeCreator is Ownable { emit OrbitTokenBridgeTemplatesUpdated(); } + /** + * @notice Deploy and initialize token bridge, both L1 and L2 sides, as part of a single TX. + * @dev This is a single entrypoint of L1 token bridge creator. Function deploys L1 side of token bridge and then uses + * 2 retryable tickets to deploy L2 side. 1st one deploy L2 factory and 2nd calls function that deploys and inits + * all the rest of the contracts. L2 chain is determined by `inbox` parameter. + */ function createTokenBridge( address inbox, uint256 maxSubmissionCostForFactory, @@ -84,10 +90,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 gasPriceBid ) external payable { address owner = msg.sender; - (address router, address standardGateway, address customGateway) = _deployL1Contracts( - inbox, - owner - ); + (address router, address standardGateway, address customGateway) = _deployL1Contracts(inbox, owner); /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls _deployL2Factory(inbox, maxSubmissionCostForFactory, maxGasForFactory, gasPriceBid); @@ -102,16 +105,14 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); } - function _deployL1Contracts( - address inbox, - address owner - ) internal returns (address router, address standardGateway, address customGateway) { + function _deployL1Contracts(address inbox, address owner) + internal + returns (address router, address standardGateway, address customGateway) + { address proxyAdmin = address(new ProxyAdmin()); // deploy router - router = address( - new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes("")) - ); + router = address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes(""))); // deploy and init gateways standardGateway = _deployL1StandardGateway(proxyAdmin, address(router), inbox); @@ -119,30 +120,17 @@ contract L1AtomicTokenBridgeCreator is Ownable { // init router L1GatewayRouter(router).initialize( - owner, - address(standardGateway), - address(0), - computeExpectedL2RouterAddress(), - inbox + owner, address(standardGateway), address(0), computeExpectedL2RouterAddress(), inbox ); // transfer ownership to owner ProxyAdmin(proxyAdmin).transferOwnership(owner); // emit it - emit OrbitTokenBridgeCreated( - address(router), - address(standardGateway), - address(customGateway), - proxyAdmin - ); + emit OrbitTokenBridgeCreated(address(router), address(standardGateway), address(customGateway), proxyAdmin); } - function _deployL1StandardGateway( - address proxyAdmin, - address router, - address inbox - ) internal returns (address) { + function _deployL1StandardGateway(address proxyAdmin, address router, address inbox) internal returns (address) { L1ERC20Gateway standardGateway = L1ERC20Gateway( address( new TransparentUpgradeableProxy( @@ -164,12 +152,10 @@ contract L1AtomicTokenBridgeCreator is Ownable { return address(standardGateway); } - function _deployL1CustomGateway( - address proxyAdmin, - address router, - address inbox, - address owner - ) internal returns (address) { + function _deployL1CustomGateway(address proxyAdmin, address router, address inbox, address owner) + internal + returns (address) + { L1CustomGateway customGateway = L1CustomGateway( address( new TransparentUpgradeableProxy( @@ -180,35 +166,18 @@ contract L1AtomicTokenBridgeCreator is Ownable { ) ); - customGateway.initialize( - computeExpectedL2CustomGatewayAddress(), - address(router), - inbox, - owner - ); + customGateway.initialize(computeExpectedL2CustomGatewayAddress(), address(router), inbox, owner); return address(customGateway); } - function _deployL2Factory( - address inbox, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid - ) internal { + function _deployL2Factory(address inbox, uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid) internal { // encode L2 factory bytecode bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - IInbox(inbox).createRetryableTicket{ value: value }( - address(0), - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - deploymentData + IInbox(inbox).createRetryableTicket{value: value}( + address(0), 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, deploymentData ); } @@ -234,15 +203,8 @@ contract L1AtomicTokenBridgeCreator is Ownable { proxyAdminOwner ); - IInbox(inbox).createRetryableTicket{ value: maxSubmissionCost + maxGas * gasPriceBid }( - expectedL2FactoryAddress, - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - maxGas, - gasPriceBid, - data + IInbox(inbox).createRetryableTicket{value: maxSubmissionCost + maxGas * gasPriceBid}( + expectedL2FactoryAddress, 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, data ); } @@ -253,17 +215,16 @@ contract L1AtomicTokenBridgeCreator is Ownable { expectedL2FactoryAddress ); - return - Create2.computeAddress( - _getSaltFrom(L2Salts.ROUTER), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2RouterLogic, expectedL2ProxyAdminAddress, bytes("")) - ) - ), - expectedL2FactoryAddress - ); + return Create2.computeAddress( + _getSaltFrom(L2Salts.ROUTER), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(expectedL2RouterLogic, expectedL2ProxyAdminAddress, bytes("")) + ) + ), + expectedL2FactoryAddress + ); } function computeExpectedL2StandardGatewayAddress() public view returns (address) { @@ -272,21 +233,16 @@ contract L1AtomicTokenBridgeCreator is Ownable { keccak256(_creationCodeFor(l2StandardGatewayTemplate.code)), expectedL2FactoryAddress ); - return - Create2.computeAddress( - _getSaltFrom(L2Salts.STANDARD_GATEWAY), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode( - expectedL2StandardGatewayLogic, - expectedL2ProxyAdminAddress, - bytes("") - ) - ) - ), - expectedL2FactoryAddress - ); + return Create2.computeAddress( + _getSaltFrom(L2Salts.STANDARD_GATEWAY), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(expectedL2StandardGatewayLogic, expectedL2ProxyAdminAddress, bytes("")) + ) + ), + expectedL2FactoryAddress + ); } function computeExpectedL2CustomGatewayAddress() public view returns (address) { @@ -296,25 +252,21 @@ contract L1AtomicTokenBridgeCreator is Ownable { expectedL2FactoryAddress ); - return - Create2.computeAddress( - _getSaltFrom(L2Salts.CUSTOM_GATEWAY), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode( - expectedL2CustomGatewayLogic, - expectedL2ProxyAdminAddress, - bytes("") - ) - ) - ), - expectedL2FactoryAddress - ); + return Create2.computeAddress( + _getSaltFrom(L2Salts.CUSTOM_GATEWAY), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(expectedL2CustomGatewayLogic, expectedL2ProxyAdminAddress, bytes("")) + ) + ), + expectedL2FactoryAddress + ); } /** - * @notice Generate a creation code that results on a contract with `code` as bytecode + * @notice Generate a creation code that results on a contract with `code` as bytecode. + * Source - https://github.com/0xsequence/sstore2/blob/master/contracts/utils/Bytecode.sol * @param code The returning value of the resulting `creationCode` * @return creationCode (constructor) for new contract */ @@ -330,53 +282,32 @@ contract L1AtomicTokenBridgeCreator is Ownable { */ - return - abi.encodePacked(hex"63", uint32(code.length), hex"80_60_0E_60_00_39_60_00_F3", code); + return abi.encodePacked(hex"63", uint32(code.length), hex"80600E6000396000F3", code); } - function _computeAddress(address _origin, uint _nonce) public pure returns (address) { + /** + * @notice Compute address of contract deployed using CREATE opcode + * @return computed address + */ + function _computeAddress(address _origin, uint256 _nonce) public pure returns (address) { bytes memory data; - if (_nonce == 0x00) + if (_nonce == 0x00) { data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, bytes1(0x80)); - else if (_nonce <= 0x7f) + } else if (_nonce <= 0x7f) { data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, uint8(_nonce)); - else if (_nonce <= 0xff) - data = abi.encodePacked( - bytes1(0xd7), - bytes1(0x94), - _origin, - bytes1(0x81), - uint8(_nonce) - ); - else if (_nonce <= 0xffff) - data = abi.encodePacked( - bytes1(0xd8), - bytes1(0x94), - _origin, - bytes1(0x82), - uint16(_nonce) - ); - else if (_nonce <= 0xffffff) - data = abi.encodePacked( - bytes1(0xd9), - bytes1(0x94), - _origin, - bytes1(0x83), - uint24(_nonce) - ); - else - data = abi.encodePacked( - bytes1(0xda), - bytes1(0x94), - _origin, - bytes1(0x84), - uint32(_nonce) - ); + } else if (_nonce <= 0xff) { + data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), _origin, bytes1(0x81), uint8(_nonce)); + } else if (_nonce <= 0xffff) { + data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), _origin, bytes1(0x82), uint16(_nonce)); + } else if (_nonce <= 0xffffff) { + data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), _origin, bytes1(0x83), uint24(_nonce)); + } else { + data = abi.encodePacked(bytes1(0xda), bytes1(0x94), _origin, bytes1(0x84), uint32(_nonce)); + } return address(uint160(uint256(keccak256(data)))); } function _getSaltFrom(bytes32 prefix) internal view returns (bytes32) { - return - keccak256(abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(this)))); + return keccak256(abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(this)))); } } diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol index 10415160e3..301e2c37b9 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol @@ -1,20 +1,15 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; -import { L1GatewayRouter } from "./gateway/L1GatewayRouter.sol"; -import { L1ERC20Gateway } from "./gateway/L1ERC20Gateway.sol"; -import { L1CustomGateway } from "./gateway/L1CustomGateway.sol"; -import { ProxyAdmin } from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol"; +import {L1ERC20Gateway} from "./gateway/L1ERC20Gateway.sol"; +import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; contract L1TokenBridgeCreator is Ownable { - event OrbitTokenBridgeCreated( - address router, - address standardGateway, - address customGateway, - address proxyAdmin - ); + event OrbitTokenBridgeCreated(address router, address standardGateway, address customGateway, address proxyAdmin); event OrbitTokenBridgeTemplatesUpdated(); L1GatewayRouter public routerTemplate; @@ -23,11 +18,10 @@ contract L1TokenBridgeCreator is Ownable { constructor() Ownable() {} - function setTemplates( - L1GatewayRouter _router, - L1ERC20Gateway _standardGateway, - L1CustomGateway _customGateway - ) external onlyOwner { + function setTemplates(L1GatewayRouter _router, L1ERC20Gateway _standardGateway, L1CustomGateway _customGateway) + external + onlyOwner + { routerTemplate = _router; standardGatewayTemplate = _standardGateway; customGatewayTemplate = _customGateway; @@ -37,9 +31,8 @@ contract L1TokenBridgeCreator is Ownable { function createTokenBridge() external { address proxyAdmin = address(new ProxyAdmin()); - L1GatewayRouter router = L1GatewayRouter( - address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes(""))) - ); + L1GatewayRouter router = + L1GatewayRouter(address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes("")))); L1ERC20Gateway standardGateway = L1ERC20Gateway( address( new TransparentUpgradeableProxy( @@ -59,12 +52,7 @@ contract L1TokenBridgeCreator is Ownable { ) ); - emit OrbitTokenBridgeCreated( - address(router), - address(standardGateway), - address(customGateway), - proxyAdmin - ); + emit OrbitTokenBridgeCreated(address(router), address(standardGateway), address(customGateway), proxyAdmin); } function initTokenBridge( @@ -81,13 +69,7 @@ contract L1TokenBridgeCreator is Ownable { ) external { /// dependencies - l2Router, l2StandardGateway, l2CustomGateway, cloneableProxyHash, l2BeaconProxyFactory, owner, inbox router.initialize(owner, address(standardGateway), address(0), l2Router, inbox); - standardGateway.initialize( - l2StandardGateway, - address(router), - inbox, - cloneableProxyHash, - l2BeaconProxyFactory - ); + standardGateway.initialize(l2StandardGateway, address(router), inbox, cloneableProxyHash, l2BeaconProxyFactory); customGateway.initialize(l2CustomGateway, address(router), inbox, owner); } } From 553569411c9b4b4255632f07d42c09b7d31b810b Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Jul 2023 14:04:14 +0200 Subject: [PATCH 096/163] Remove comment --- test-e2e/tokenBridgeDeploymentTest.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index e2d5540b64..3a6fb89add 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -147,11 +147,6 @@ async function checkL1RouterInitialization(l1Router: L1GatewayRouter) { _l2Network.tokenBridge.l1ERC20Gateway.toLowerCase() ) - // TODO - generic way to check owner - // expect((await l1Router.owner()).toLowerCase()).to.be.eq( - // (await l1Signer.getAddress().toLowerCase() - // ) - expect((await l1Router.inbox()).toLowerCase()).to.be.eq( _l2Network.ethBridge.inbox.toLowerCase() ) From 30c233e6a6d479f0473e9a369ee0618cd074ba33 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Jul 2023 19:36:35 +0200 Subject: [PATCH 097/163] Deploy L2 Weth and WethGateway --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 55 +++++++++++ .../ethereum/L1AtomicTokenBridgeCreator.sol | 95 +++++++++++++++++-- .../atomicTokenBridgeDeployer.ts | 33 ++++++- 3 files changed, 169 insertions(+), 14 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 420900b929..3c19da10ba 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -4,8 +4,10 @@ pragma solidity ^0.8.4; import {L2GatewayRouter} from "./gateway/L2GatewayRouter.sol"; import {L2ERC20Gateway} from "./gateway/L2ERC20Gateway.sol"; import {L2CustomGateway} from "./gateway/L2CustomGateway.sol"; +import {L2WethGateway} from "./gateway/L2WethGateway.sol"; import {StandardArbERC20} from "./StandardArbERC20.sol"; import {BeaconProxyFactory} from "../libraries/ClonableBeaconProxy.sol"; +import {aeWETH} from "../libraries/aeWETH.sol"; import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; @@ -21,9 +23,13 @@ contract L2AtomicTokenBridgeFactory { bytes memory routerCreationCode, bytes memory standardGatewayCreationCode, bytes memory customGatewayCreationCode, + bytes memory wethGatewayCreationCode, + bytes memory aeWethCreationCode, address l1Router, address l1StandardGateway, address l1CustomGateway, + address l1WethGateway, + address l1Weth, address l2StandardGatewayExpectedAddress, address proxyAdminOwner ) external { @@ -34,6 +40,7 @@ contract L2AtomicTokenBridgeFactory { address router = _deployRouter(routerCreationCode, l1Router, l2StandardGatewayExpectedAddress, proxyAdmin); _deployStandardGateway(standardGatewayCreationCode, l1StandardGateway, router, proxyAdmin); _deployCustomGateway(customGatewayCreationCode, l1CustomGateway, router, proxyAdmin); + _deployWethGateway(wethGatewayCreationCode, aeWethCreationCode, l1WethGateway, l1Weth, router, proxyAdmin); // transfer ownership to L1Creator's msg.sender ProxyAdmin(proxyAdmin).transferOwnership(proxyAdminOwner); @@ -121,6 +128,50 @@ contract L2AtomicTokenBridgeFactory { customGateway.initialize(l1CustomGateway, router); } + function _deployWethGateway( + bytes memory wethGatewayCreationCode, + bytes memory aeWethCreationCode, + address l1WethGateway, + address l1Weth, + address router, + address proxyAdmin + ) internal { + // L2 WETH + address aeWethLogic = Create2.deploy(0, _getSaltFrom(L2Salts.WETH_LOGIC), aeWethCreationCode); + aeWETH l2Weth = aeWETH( + payable( + address( + new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.WETH) }( + aeWethLogic, + proxyAdmin, + bytes("") + ) + ) + ) + ); + + // WETH gateway + address wethGatewayLogicAddress = + Create2.deploy(0, _getSaltFrom(L2Salts.WETH_GATEWAY_LOGIC), wethGatewayCreationCode); + L2WethGateway wethGateway = L2WethGateway( + payable( + address( + new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.WETH_GATEWAY) }( + wethGatewayLogicAddress, + proxyAdmin, + bytes("") + ) + ) + ) + ); + + // init gateway + wethGateway.initialize(l1WethGateway, router, l1Weth, address(l2Weth)); + + // init L2Weth + l2Weth.initialize("WETH", "WETH", 18, address(wethGateway), l1Weth); + } + function _getSaltFrom(bytes32 prefix) internal view returns (bytes32) { return keccak256(abi.encodePacked(prefix, msg.sender)); } @@ -137,6 +188,10 @@ library L2Salts { bytes32 public constant STANDARD_GATEWAY = keccak256(bytes("OrbitL2StandardGatewayProxy")); bytes32 public constant CUSTOM_GATEWAY_LOGIC = keccak256(bytes("OrbitL2CustomGatewayLogic")); bytes32 public constant CUSTOM_GATEWAY = keccak256(bytes("OrbitL2CustomGatewayProxy")); + bytes32 public constant WETH_GATEWAY_LOGIC = keccak256(bytes("OrbitL2WethGatewayLogic")); + bytes32 public constant WETH_GATEWAY = keccak256(bytes("OrbitL2WethGatewayProxy")); + bytes32 public constant WETH_LOGIC = keccak256(bytes("OrbitL2WETH")); + bytes32 public constant WETH = keccak256(bytes("OrbitL2WETHProxy")); bytes32 public constant STANDARD_ERC20 = keccak256(bytes("OrbitStandardArbERC20")); bytes32 public constant UPGRADEABLE_BEACON = keccak256(bytes("OrbitUpgradeableBeacon")); bytes32 public constant BEACON_PROXY_FACTORY = keccak256(bytes("OrbitBeaconProxyFactory")); diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 5e87f6aef2..f66fe3b8ff 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.4; import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol"; import {L1ERC20Gateway} from "./gateway/L1ERC20Gateway.sol"; import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; +import {L1WethGateway} from "./gateway/L1WethGateway.sol"; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {L2AtomicTokenBridgeFactory, L2Salts} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; @@ -25,15 +26,21 @@ contract L1AtomicTokenBridgeCreator is Ownable { L1GatewayRouter public routerTemplate; L1ERC20Gateway public standardGatewayTemplate; L1CustomGateway public customGatewayTemplate; + L1WethGateway public wethGatewayTemplate; address public l2TokenBridgeFactoryTemplate; address public l2RouterTemplate; address public l2StandardGatewayTemplate; address public l2CustomGatewayTemplate; + address public l2WethGatewayTemplate; + address public l2WethTemplate; + + address public l1Weth; address public immutable expectedL2FactoryAddress; address public immutable expectedL2ProxyAdminAddress; address public immutable expectedL2BeaconProxyFactoryAddress; + address public immutable expectedL2WethAddress; constructor() Ownable() { expectedL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); @@ -47,6 +54,21 @@ contract L1AtomicTokenBridgeCreator is Ownable { keccak256(type(BeaconProxyFactory).creationCode), expectedL2FactoryAddress ); + + address expectedL2WethLogicAddress = Create2.computeAddress( + _getSaltFrom(L2Salts.WETH_LOGIC), keccak256(type(BeaconProxyFactory).creationCode), expectedL2FactoryAddress + ); + + expectedL2WethAddress = Create2.computeAddress( + _getSaltFrom(L2Salts.BEACON_PROXY_FACTORY), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(expectedL2WethLogicAddress, expectedL2ProxyAdminAddress, bytes("")) + ) + ), + expectedL2FactoryAddress + ); } /** @@ -58,19 +80,28 @@ contract L1AtomicTokenBridgeCreator is Ownable { L1GatewayRouter _router, L1ERC20Gateway _standardGateway, L1CustomGateway _customGateway, + L1WethGateway _wethGatewayTemplate, address _l2TokenBridgeFactoryTemplate, address _l2RouterTemplate, address _l2StandardGatewayTemplate, - address _l2CustomGatewayTemplate + address _l2CustomGatewayTemplate, + address _l2WethGatewayTemplate, + address _l2WethTemplate, + address _l1Weth ) external onlyOwner { routerTemplate = _router; standardGatewayTemplate = _standardGateway; customGatewayTemplate = _customGateway; + wethGatewayTemplate = _wethGatewayTemplate; l2TokenBridgeFactoryTemplate = _l2TokenBridgeFactoryTemplate; l2RouterTemplate = _l2RouterTemplate; l2StandardGatewayTemplate = _l2StandardGatewayTemplate; l2CustomGatewayTemplate = _l2CustomGatewayTemplate; + l2WethGatewayTemplate = _l2WethGatewayTemplate; + l2WethTemplate = _l2WethTemplate; + + l1Weth = _l1Weth; emit OrbitTokenBridgeTemplatesUpdated(); } @@ -90,14 +121,16 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 gasPriceBid ) external payable { address owner = msg.sender; - (address router, address standardGateway, address customGateway) = _deployL1Contracts(inbox, owner); + (address router, address standardGateway, address customGateway, address wethGateway) = + _deployL1Contracts(inbox, owner); /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls _deployL2Factory(inbox, maxSubmissionCostForFactory, maxGasForFactory, gasPriceBid); _deployL2Contracts( - address(router), - address(standardGateway), - address(customGateway), + router, + standardGateway, + customGateway, + wethGateway, inbox, maxSubmissionCostForContracts, maxGasForContracts, @@ -107,7 +140,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { function _deployL1Contracts(address inbox, address owner) internal - returns (address router, address standardGateway, address customGateway) + returns (address router, address standardGateway, address customGateway, address wethGateway) { address proxyAdmin = address(new ProxyAdmin()); @@ -115,8 +148,9 @@ contract L1AtomicTokenBridgeCreator is Ownable { router = address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes(""))); // deploy and init gateways - standardGateway = _deployL1StandardGateway(proxyAdmin, address(router), inbox); - customGateway = _deployL1CustomGateway(proxyAdmin, address(router), inbox, owner); + standardGateway = _deployL1StandardGateway(proxyAdmin, router, inbox); + customGateway = _deployL1CustomGateway(proxyAdmin, router, inbox, owner); + wethGateway = _deployL1WethGateway(proxyAdmin, router, inbox); // init router L1GatewayRouter(router).initialize( @@ -166,11 +200,30 @@ contract L1AtomicTokenBridgeCreator is Ownable { ) ); - customGateway.initialize(computeExpectedL2CustomGatewayAddress(), address(router), inbox, owner); + customGateway.initialize(computeExpectedL2CustomGatewayAddress(), router, inbox, owner); return address(customGateway); } + function _deployL1WethGateway(address proxyAdmin, address router, address inbox) internal returns (address) { + L1WethGateway wethGateway = L1WethGateway( + payable( + address( + new TransparentUpgradeableProxy( + address(wethGatewayTemplate), + proxyAdmin, + bytes("") + ) + ) + ) + ); + + // wethGateway.initialize(computeExpectedL2WethGatewayAddress(), router, l1Weth, l2Weth); + wethGateway.initialize(computeExpectedL2WethGatewayAddress(), router, inbox, l1Weth, address(2)); + + return address(wethGateway); + } + function _deployL2Factory(address inbox, uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid) internal { // encode L2 factory bytecode bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); @@ -185,6 +238,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { address l1Router, address l1StandardGateway, address l1CustomGateway, + address l1WethGateway, address inbox, uint256 maxSubmissionCost, uint256 maxGas, @@ -196,9 +250,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { _creationCodeFor(l2RouterTemplate.code), _creationCodeFor(l2StandardGatewayTemplate.code), _creationCodeFor(l2CustomGatewayTemplate.code), + _creationCodeFor(l2WethGatewayTemplate.code), + _creationCodeFor(l2WethTemplate.code), l1Router, l1StandardGateway, l1CustomGateway, + l1WethGateway, + l1Weth, computeExpectedL2StandardGatewayAddress(), proxyAdminOwner ); @@ -264,6 +322,25 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); } + function computeExpectedL2WethGatewayAddress() public view returns (address) { + address expectedL2WethGatewayLogic = Create2.computeAddress( + _getSaltFrom(L2Salts.WETH_GATEWAY_LOGIC), + keccak256(_creationCodeFor(l2WethGatewayTemplate.code)), + expectedL2FactoryAddress + ); + + return Create2.computeAddress( + _getSaltFrom(L2Salts.WETH_GATEWAY), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(expectedL2WethGatewayLogic, expectedL2ProxyAdminAddress, bytes("")) + ) + ), + expectedL2FactoryAddress + ); + } + /** * @notice Generate a creation code that results on a contract with `code` as bytecode. * Source - https://github.com/0xsequence/sstore2/blob/master/contracts/utils/Bytecode.sol diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 4eebabf5f5..de033e69a2 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -9,6 +9,9 @@ import { L2ERC20Gateway__factory, L2CustomGateway__factory, L1AtomicTokenBridgeCreator, + L2WethGateway__factory, + AeWETH__factory, + L1WethGateway__factory, } from '../../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { @@ -157,6 +160,10 @@ export const createTokenBridge = async ( L2GatewayRouter__factory.bytecode, L2ERC20Gateway__factory.bytecode, L2CustomGateway__factory.bytecode, + L2WethGateway__factory.bytecode, + AeWETH__factory.bytecode, + ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, @@ -263,7 +270,7 @@ const deployL1TokenBridgeCreator = async (l1Signer: Signer) => { ).deploy() await l1TokenBridgeCreator.deployed() - /// deploy logic contracts + /// deploy L1 logic contracts const routerTemplate = await new L1GatewayRouter__factory(l1Signer).deploy() await routerTemplate.deployed() @@ -277,39 +284,55 @@ const deployL1TokenBridgeCreator = async (l1Signer: Signer) => { ).deploy() await customGatewayTemplate.deployed() + const wethGatewayTemplate = await new L1WethGateway__factory( + l1Signer + ).deploy() + await wethGatewayTemplate.deployed() + /// deploy L2 contracts as placeholders on L1 const l2TokenBridgeFactoryOnL1 = await new L2AtomicTokenBridgeFactory__factory(l1Signer).deploy() await l2TokenBridgeFactoryOnL1.deployed() - /// deploy router const l2GatewayRouterOnL1 = await new L2GatewayRouter__factory( l1Signer ).deploy() await l2GatewayRouterOnL1.deployed() - /// deploy standard gateway const l2StandardGatewayAddressOnL1 = await new L2ERC20Gateway__factory( l1Signer ).deploy() await l2StandardGatewayAddressOnL1.deployed() - /// deploy custom gateway const l2CustomGatewayAddressOnL1 = await new L2CustomGateway__factory( l1Signer ).deploy() await l2CustomGatewayAddressOnL1.deployed() + const l2WethGatewayAddressOnL1 = await new L2WethGateway__factory( + l1Signer + ).deploy() + await l2WethGatewayAddressOnL1.deployed() + + const l2WethAddressOnL1 = await new AeWETH__factory(l1Signer).deploy() + await l2WethAddressOnL1.deployed() + + const weth = ethers.Wallet.createRandom().address + await ( await l1TokenBridgeCreator.setTemplates( routerTemplate.address, standardGatewayTemplate.address, customGatewayTemplate.address, + wethGatewayTemplate.address, l2TokenBridgeFactoryOnL1.address, l2GatewayRouterOnL1.address, l2StandardGatewayAddressOnL1.address, - l2CustomGatewayAddressOnL1.address + l2CustomGatewayAddressOnL1.address, + l2WethGatewayAddressOnL1.address, + l2WethAddressOnL1.address, + weth ) ).wait() From ccf17c92945f06ef9790e7be5b2a4e145539139a Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 5 Jul 2023 20:09:56 +0200 Subject: [PATCH 098/163] Update tests and fix weth bugs --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 44 ++++++++++--------- .../atomicTokenBridgeDeployer.ts | 21 ++++++--- test-e2e/tokenBridgeDeploymentTest.ts | 24 +++++----- 3 files changed, 52 insertions(+), 37 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index f66fe3b8ff..7f8f431017 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -20,7 +20,9 @@ import {BeaconProxyFactory, ClonableBeaconProxy} from "../libraries/ClonableBeac * @dev Throughout the contract terms L1 and L2 are used, but those can be considered as base (N) chain and child (N+1) chain */ contract L1AtomicTokenBridgeCreator is Ownable { - event OrbitTokenBridgeCreated(address router, address standardGateway, address customGateway, address proxyAdmin); + event OrbitTokenBridgeCreated( + address router, address standardGateway, address customGateway, address wethGateway, address proxyAdmin + ); event OrbitTokenBridgeTemplatesUpdated(); L1GatewayRouter public routerTemplate; @@ -40,7 +42,6 @@ contract L1AtomicTokenBridgeCreator is Ownable { address public immutable expectedL2FactoryAddress; address public immutable expectedL2ProxyAdminAddress; address public immutable expectedL2BeaconProxyFactoryAddress; - address public immutable expectedL2WethAddress; constructor() Ownable() { expectedL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); @@ -54,21 +55,6 @@ contract L1AtomicTokenBridgeCreator is Ownable { keccak256(type(BeaconProxyFactory).creationCode), expectedL2FactoryAddress ); - - address expectedL2WethLogicAddress = Create2.computeAddress( - _getSaltFrom(L2Salts.WETH_LOGIC), keccak256(type(BeaconProxyFactory).creationCode), expectedL2FactoryAddress - ); - - expectedL2WethAddress = Create2.computeAddress( - _getSaltFrom(L2Salts.BEACON_PROXY_FACTORY), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2WethLogicAddress, expectedL2ProxyAdminAddress, bytes("")) - ) - ), - expectedL2FactoryAddress - ); } /** @@ -161,7 +147,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { ProxyAdmin(proxyAdmin).transferOwnership(owner); // emit it - emit OrbitTokenBridgeCreated(address(router), address(standardGateway), address(customGateway), proxyAdmin); + emit OrbitTokenBridgeCreated(router, standardGateway, customGateway, wethGateway, proxyAdmin); } function _deployL1StandardGateway(address proxyAdmin, address router, address inbox) internal returns (address) { @@ -218,8 +204,9 @@ contract L1AtomicTokenBridgeCreator is Ownable { ) ); - // wethGateway.initialize(computeExpectedL2WethGatewayAddress(), router, l1Weth, l2Weth); - wethGateway.initialize(computeExpectedL2WethGatewayAddress(), router, inbox, l1Weth, address(2)); + wethGateway.initialize( + computeExpectedL2WethGatewayAddress(), router, inbox, l1Weth, computeExpectedL2WethAddress() + ); return address(wethGateway); } @@ -341,6 +328,23 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); } + function computeExpectedL2WethAddress() public view returns (address) { + address expectedL2WethLogic = Create2.computeAddress( + _getSaltFrom(L2Salts.WETH_LOGIC), keccak256(_creationCodeFor(l2WethTemplate.code)), expectedL2FactoryAddress + ); + + return Create2.computeAddress( + _getSaltFrom(L2Salts.WETH), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(expectedL2WethLogic, expectedL2ProxyAdminAddress, bytes("")) + ) + ), + expectedL2FactoryAddress + ); + } + /** * @notice Generate a creation code that results on a contract with `code` as bytecode. * Source - https://github.com/0xsequence/sstore2/blob/master/contracts/utils/Bytecode.sol diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index de033e69a2..4d6a833d2b 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -98,16 +98,16 @@ export const setupTokenBridgeInLocalEnv = async ( l1GatewayRouter: deployedContracts.l1Router, l1MultiCall: '', l1ProxyAdmin: deployedContracts.l1ProxyAdmin, - l1Weth: '', - l1WethGateway: '', + l1Weth: deployedContracts.l1Weth, + l1WethGateway: deployedContracts.l1WethGateway, l2CustomGateway: deployedContracts.l2CustomGateway, l2ERC20Gateway: deployedContracts.l2StandardGateway, l2GatewayRouter: deployedContracts.l2Router, l2Multicall: '', l2ProxyAdmin: deployedContracts.l2ProxyAdmin, - l2Weth: '', - l2WethGateway: '', + l2Weth: deployedContracts.l2Weth, + l2WethGateway: deployedContracts.l2WethGateway, }, } @@ -232,6 +232,7 @@ export const createTokenBridge = async ( router: l1Router, standardGateway: l1StandardGateway, customGateway: l1CustomGateway, + wethGateway: l1WethGateway, proxyAdmin: l1ProxyAdmin, } = getParsedLogs( receipt.logs, @@ -239,7 +240,7 @@ export const createTokenBridge = async ( 'OrbitTokenBridgeCreated' )[0].args - /// pick up L2 contracts from L1 factory contract + /// pick up L2 contracts const l2Router = await l1TokenBridgeCreator.computeExpectedL2RouterAddress() const l2StandardGateway = L2ERC20Gateway__factory.connect( await l1TokenBridgeCreator.computeExpectedL2StandardGatewayAddress(), @@ -248,16 +249,26 @@ export const createTokenBridge = async ( const beaconProxyFactory = await l2StandardGateway.beaconProxyFactory() const l2CustomGateway = await l1TokenBridgeCreator.computeExpectedL2CustomGatewayAddress() + const l2WethGateway = L2WethGateway__factory.connect( + await l1TokenBridgeCreator.computeExpectedL2WethGatewayAddress(), + l2Signer + ) + const l1Weth = await l2WethGateway.l1Weth() + const l2Weth = await l2WethGateway.l2Weth() const l2ProxyAdmin = await l1TokenBridgeCreator.expectedL2ProxyAdminAddress() return { l1Router, l1StandardGateway, l1CustomGateway, + l1WethGateway, l1ProxyAdmin, l2Router, l2StandardGateway: l2StandardGateway.address, l2CustomGateway, + l2WethGateway: l2WethGateway.address, + l1Weth, + l2Weth, beaconProxyFactory, l2ProxyAdmin, } diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index 3a6fb89add..42bf597548 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -80,12 +80,12 @@ describe('tokenBridge', () => { ) ) - // await checkL1WethGatewayInitialization( - // L1WethGateway__factory.connect( - // _l2Network.tokenBridge.l1WethGateway, - // l1Provider - // ) - // ) + await checkL1WethGatewayInitialization( + L1WethGateway__factory.connect( + _l2Network.tokenBridge.l1WethGateway, + l1Provider + ) + ) //// L2 checks @@ -129,12 +129,12 @@ describe('tokenBridge', () => { ) ) - // await checkL2WethGatewayInitialization( - // L2WethGateway__factory.connect( - // _l2Network.tokenBridge.l2WethGateway, - // l2Provider - // ) - // ) + await checkL2WethGatewayInitialization( + L2WethGateway__factory.connect( + _l2Network.tokenBridge.l2WethGateway, + l2Provider + ) + ) }) }) From f9354230b3bd9cec705736c5d453cefcbb4fa705 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jul 2023 10:11:35 +0200 Subject: [PATCH 099/163] Use CREATE2 on L1 as well, using inbox address in the salt --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 75 ++++++++++--------- .../arbitrum/L2TokenBridgeFactory.sol | 1 + .../ethereum/L1AtomicTokenBridgeCreator.sol | 46 +++++++----- 3 files changed, 67 insertions(+), 55 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 3c19da10ba..05c68f82bc 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -34,7 +34,7 @@ contract L2AtomicTokenBridgeFactory { address proxyAdminOwner ) external { // create proxyAdmin which will be used for all contracts - address proxyAdmin = address(new ProxyAdmin{ salt: _getSaltFrom(L2Salts.PROXY_ADMIN) }()); + address proxyAdmin = address(new ProxyAdmin{ salt: _getL2Salt(OrbitSalts.L2_PROXY_ADMIN) }()); // deploy router/gateways address router = _deployRouter(routerCreationCode, l1Router, l2StandardGatewayExpectedAddress, proxyAdmin); @@ -53,10 +53,10 @@ contract L2AtomicTokenBridgeFactory { address proxyAdmin ) internal returns (address) { // create logic and proxy - address routerLogicAddress = Create2.deploy(0, _getSaltFrom(L2Salts.ROUTER_LOGIC), creationCode); + address routerLogicAddress = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), creationCode); L2GatewayRouter router = L2GatewayRouter( address( - new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.ROUTER) }( + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_ROUTER) }( routerLogicAddress, proxyAdmin, bytes("") @@ -78,26 +78,24 @@ contract L2AtomicTokenBridgeFactory { ) internal { // create logic and proxy address standardGatewayLogicAddress = - Create2.deploy(0, _getSaltFrom(L2Salts.STANDARD_GATEWAY_LOGIC), creationCode); + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), creationCode); L2ERC20Gateway standardGateway = L2ERC20Gateway( address( - new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.STANDARD_GATEWAY) }( - standardGatewayLogicAddress, - proxyAdmin, - bytes("") - ) + new TransparentUpgradeableProxy{ + salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY) + }(standardGatewayLogicAddress, proxyAdmin, bytes("")) ) ); // create beacon StandardArbERC20 standardArbERC20 = new StandardArbERC20{ - salt: _getSaltFrom(L2Salts.STANDARD_ERC20) + salt: _getL2Salt(OrbitSalts.L2_STANDARD_ERC20) }(); UpgradeableBeacon beacon = new UpgradeableBeacon{ - salt: _getSaltFrom(L2Salts.UPGRADEABLE_BEACON) + salt: _getL2Salt(OrbitSalts.UPGRADEABLE_BEACON) }(address(standardArbERC20)); BeaconProxyFactory beaconProxyFactory = new BeaconProxyFactory{ - salt: _getSaltFrom(L2Salts.BEACON_PROXY_FACTORY) + salt: _getL2Salt(OrbitSalts.BEACON_PROXY_FACTORY) }(); // init contracts @@ -111,12 +109,13 @@ contract L2AtomicTokenBridgeFactory { address router, address proxyAdmin ) internal { - address customGatewayLogicAddress = Create2.deploy(0, _getSaltFrom(L2Salts.CUSTOM_GATEWAY_LOGIC), creationCode); + address customGatewayLogicAddress = + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), creationCode); // create logic and proxy L2CustomGateway customGateway = L2CustomGateway( address( - new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.CUSTOM_GATEWAY) }( + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY) }( customGatewayLogicAddress, proxyAdmin, bytes("") @@ -137,11 +136,11 @@ contract L2AtomicTokenBridgeFactory { address proxyAdmin ) internal { // L2 WETH - address aeWethLogic = Create2.deploy(0, _getSaltFrom(L2Salts.WETH_LOGIC), aeWethCreationCode); + address aeWethLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_LOGIC), aeWethCreationCode); aeWETH l2Weth = aeWETH( payable( address( - new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.WETH) }( + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH) }( aeWethLogic, proxyAdmin, bytes("") @@ -152,15 +151,13 @@ contract L2AtomicTokenBridgeFactory { // WETH gateway address wethGatewayLogicAddress = - Create2.deploy(0, _getSaltFrom(L2Salts.WETH_GATEWAY_LOGIC), wethGatewayCreationCode); + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), wethGatewayCreationCode); L2WethGateway wethGateway = L2WethGateway( payable( address( - new TransparentUpgradeableProxy{ salt: _getSaltFrom(L2Salts.WETH_GATEWAY) }( - wethGatewayLogicAddress, - proxyAdmin, - bytes("") - ) + new TransparentUpgradeableProxy{ + salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY) + }(wethGatewayLogicAddress, proxyAdmin, bytes("")) ) ) ); @@ -172,7 +169,7 @@ contract L2AtomicTokenBridgeFactory { l2Weth.initialize("WETH", "WETH", 18, address(wethGateway), l1Weth); } - function _getSaltFrom(bytes32 prefix) internal view returns (bytes32) { + function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { return keccak256(abi.encodePacked(prefix, msg.sender)); } } @@ -180,19 +177,25 @@ contract L2AtomicTokenBridgeFactory { /** * Collection of salts used in CREATE2 deployment of L2 token bridge contracts. */ -library L2Salts { - bytes32 public constant PROXY_ADMIN = keccak256(bytes("OrbitL2ProxyAdmin")); - bytes32 public constant ROUTER_LOGIC = keccak256(bytes("OrbitL2GatewayRouterLogic")); - bytes32 public constant ROUTER = keccak256(bytes("OrbitL2GatewayRouterProxy")); - bytes32 public constant STANDARD_GATEWAY_LOGIC = keccak256(bytes("OrbitL2StandardGatewayLogic")); - bytes32 public constant STANDARD_GATEWAY = keccak256(bytes("OrbitL2StandardGatewayProxy")); - bytes32 public constant CUSTOM_GATEWAY_LOGIC = keccak256(bytes("OrbitL2CustomGatewayLogic")); - bytes32 public constant CUSTOM_GATEWAY = keccak256(bytes("OrbitL2CustomGatewayProxy")); - bytes32 public constant WETH_GATEWAY_LOGIC = keccak256(bytes("OrbitL2WethGatewayLogic")); - bytes32 public constant WETH_GATEWAY = keccak256(bytes("OrbitL2WethGatewayProxy")); - bytes32 public constant WETH_LOGIC = keccak256(bytes("OrbitL2WETH")); - bytes32 public constant WETH = keccak256(bytes("OrbitL2WETHProxy")); - bytes32 public constant STANDARD_ERC20 = keccak256(bytes("OrbitStandardArbERC20")); +library OrbitSalts { + bytes32 public constant L1_PROXY_ADMIN = keccak256(bytes("OrbitL1ProxyAdmin")); + bytes32 public constant L1_ROUTER = keccak256(bytes("OrbitL1GatewayRouterProxy")); + bytes32 public constant L1_STANDARD_GATEWAY = keccak256(bytes("OrbitL1StandardGatewayProxy")); + bytes32 public constant L1_CUSTOM_GATEWAY = keccak256(bytes("OrbitL1CustomGatewayProxy")); + bytes32 public constant L1_WETH_GATEWAY = keccak256(bytes("OrbitL1WethGatewayProxy")); + + bytes32 public constant L2_PROXY_ADMIN = keccak256(bytes("OrbitL2ProxyAdmin")); + bytes32 public constant L2_ROUTER_LOGIC = keccak256(bytes("OrbitL2GatewayRouterLogic")); + bytes32 public constant L2_ROUTER = keccak256(bytes("OrbitL2GatewayRouterProxy")); + bytes32 public constant L2_STANDARD_GATEWAY_LOGIC = keccak256(bytes("OrbitL2StandardGatewayLogic")); + bytes32 public constant L2_STANDARD_GATEWAY = keccak256(bytes("OrbitL2StandardGatewayProxy")); + bytes32 public constant L2_CUSTOM_GATEWAY_LOGIC = keccak256(bytes("OrbitL2CustomGatewayLogic")); + bytes32 public constant L2_CUSTOM_GATEWAY = keccak256(bytes("OrbitL2CustomGatewayProxy")); + bytes32 public constant L2_WETH_GATEWAY_LOGIC = keccak256(bytes("OrbitL2WethGatewayLogic")); + bytes32 public constant L2_WETH_GATEWAY = keccak256(bytes("OrbitL2WethGatewayProxy")); + bytes32 public constant L2_WETH_LOGIC = keccak256(bytes("OrbitL2WETH")); + bytes32 public constant L2_WETH = keccak256(bytes("OrbitL2WETHProxy")); + bytes32 public constant L2_STANDARD_ERC20 = keccak256(bytes("OrbitStandardArbERC20")); bytes32 public constant UPGRADEABLE_BEACON = keccak256(bytes("OrbitUpgradeableBeacon")); bytes32 public constant BEACON_PROXY_FACTORY = keccak256(bytes("OrbitBeaconProxyFactory")); } diff --git a/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol index 401557512d..08c04a125a 100644 --- a/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; import {L2GatewayRouter} from "./gateway/L2GatewayRouter.sol"; diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 7f8f431017..c91438fdad 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -7,7 +7,7 @@ import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; import {L1WethGateway} from "./gateway/L1WethGateway.sol"; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import {L2AtomicTokenBridgeFactory, L2Salts} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; +import {L2AtomicTokenBridgeFactory, OrbitSalts} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IInbox} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; @@ -47,11 +47,11 @@ contract L1AtomicTokenBridgeCreator is Ownable { expectedL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); expectedL2ProxyAdminAddress = Create2.computeAddress( - _getSaltFrom(L2Salts.PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), expectedL2FactoryAddress + _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), expectedL2FactoryAddress ); expectedL2BeaconProxyFactoryAddress = Create2.computeAddress( - _getSaltFrom(L2Salts.BEACON_PROXY_FACTORY), + _getL2Salt(OrbitSalts.BEACON_PROXY_FACTORY), keccak256(type(BeaconProxyFactory).creationCode), expectedL2FactoryAddress ); @@ -128,10 +128,12 @@ contract L1AtomicTokenBridgeCreator is Ownable { internal returns (address router, address standardGateway, address customGateway, address wethGateway) { - address proxyAdmin = address(new ProxyAdmin()); + address proxyAdmin = address(new ProxyAdmin{ salt: _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox) }()); // deploy router - router = address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes(""))); + router = address( + new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_ROUTER, inbox) }(address(routerTemplate), proxyAdmin, bytes("")) + ); // deploy and init gateways standardGateway = _deployL1StandardGateway(proxyAdmin, router, inbox); @@ -153,7 +155,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { function _deployL1StandardGateway(address proxyAdmin, address router, address inbox) internal returns (address) { L1ERC20Gateway standardGateway = L1ERC20Gateway( address( - new TransparentUpgradeableProxy( + new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_STANDARD_GATEWAY, inbox) }( address(standardGatewayTemplate), proxyAdmin, bytes("") @@ -178,7 +180,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { { L1CustomGateway customGateway = L1CustomGateway( address( - new TransparentUpgradeableProxy( + new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_CUSTOM_GATEWAY, inbox) }( address(customGatewayTemplate), proxyAdmin, bytes("") @@ -195,7 +197,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { L1WethGateway wethGateway = L1WethGateway( payable( address( - new TransparentUpgradeableProxy( + new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_WETH_GATEWAY, inbox) }( address(wethGatewayTemplate), proxyAdmin, bytes("") @@ -255,13 +257,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { function computeExpectedL2RouterAddress() public view returns (address) { address expectedL2RouterLogic = Create2.computeAddress( - _getSaltFrom(L2Salts.ROUTER_LOGIC), + _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), keccak256(_creationCodeFor(l2RouterTemplate.code)), expectedL2FactoryAddress ); return Create2.computeAddress( - _getSaltFrom(L2Salts.ROUTER), + _getL2Salt(OrbitSalts.L2_ROUTER), keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, @@ -274,12 +276,12 @@ contract L1AtomicTokenBridgeCreator is Ownable { function computeExpectedL2StandardGatewayAddress() public view returns (address) { address expectedL2StandardGatewayLogic = Create2.computeAddress( - _getSaltFrom(L2Salts.STANDARD_GATEWAY_LOGIC), + _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), keccak256(_creationCodeFor(l2StandardGatewayTemplate.code)), expectedL2FactoryAddress ); return Create2.computeAddress( - _getSaltFrom(L2Salts.STANDARD_GATEWAY), + _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY), keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, @@ -292,13 +294,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { function computeExpectedL2CustomGatewayAddress() public view returns (address) { address expectedL2CustomGatewayLogic = Create2.computeAddress( - _getSaltFrom(L2Salts.CUSTOM_GATEWAY_LOGIC), + _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), keccak256(_creationCodeFor(l2CustomGatewayTemplate.code)), expectedL2FactoryAddress ); return Create2.computeAddress( - _getSaltFrom(L2Salts.CUSTOM_GATEWAY), + _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY), keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, @@ -311,13 +313,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { function computeExpectedL2WethGatewayAddress() public view returns (address) { address expectedL2WethGatewayLogic = Create2.computeAddress( - _getSaltFrom(L2Salts.WETH_GATEWAY_LOGIC), + _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), keccak256(_creationCodeFor(l2WethGatewayTemplate.code)), expectedL2FactoryAddress ); return Create2.computeAddress( - _getSaltFrom(L2Salts.WETH_GATEWAY), + _getL2Salt(OrbitSalts.L2_WETH_GATEWAY), keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, @@ -330,11 +332,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { function computeExpectedL2WethAddress() public view returns (address) { address expectedL2WethLogic = Create2.computeAddress( - _getSaltFrom(L2Salts.WETH_LOGIC), keccak256(_creationCodeFor(l2WethTemplate.code)), expectedL2FactoryAddress + _getL2Salt(OrbitSalts.L2_WETH_LOGIC), + keccak256(_creationCodeFor(l2WethTemplate.code)), + expectedL2FactoryAddress ); return Create2.computeAddress( - _getSaltFrom(L2Salts.WETH), + _getL2Salt(OrbitSalts.L2_WETH), keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, @@ -388,7 +392,11 @@ contract L1AtomicTokenBridgeCreator is Ownable { return address(uint160(uint256(keccak256(data)))); } - function _getSaltFrom(bytes32 prefix) internal view returns (bytes32) { + function _getL1Salt(bytes32 prefix, address inbox) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(prefix, inbox)); + } + + function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { return keccak256(abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(this)))); } } From eca0062b5c004dd4112466313577f7e6865b69df Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jul 2023 10:28:58 +0200 Subject: [PATCH 100/163] Set rollup owner to own token bridge --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 42 ++++++++++--------- test-e2e/tokenBridgeDeploymentTest.ts | 21 ++++++---- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index c91438fdad..04c1c55b4a 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -9,7 +9,7 @@ import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.s import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {L2AtomicTokenBridgeFactory, OrbitSalts} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {IInbox} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; +import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; import {BeaconProxyFactory, ClonableBeaconProxy} from "../libraries/ClonableBeaconProxy.sol"; @@ -106,7 +106,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 maxGasForContracts, uint256 gasPriceBid ) external payable { - address owner = msg.sender; + address owner = _getRollupOwner(inbox); (address router, address standardGateway, address customGateway, address wethGateway) = _deployL1Contracts(inbox, owner); @@ -132,7 +132,11 @@ contract L1AtomicTokenBridgeCreator is Ownable { // deploy router router = address( - new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_ROUTER, inbox) }(address(routerTemplate), proxyAdmin, bytes("")) + new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_ROUTER, inbox) }( + address(routerTemplate), + proxyAdmin, + bytes("") + ) ); // deploy and init gateways @@ -155,11 +159,9 @@ contract L1AtomicTokenBridgeCreator is Ownable { function _deployL1StandardGateway(address proxyAdmin, address router, address inbox) internal returns (address) { L1ERC20Gateway standardGateway = L1ERC20Gateway( address( - new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_STANDARD_GATEWAY, inbox) }( - address(standardGatewayTemplate), - proxyAdmin, - bytes("") - ) + new TransparentUpgradeableProxy{ + salt: _getL1Salt(OrbitSalts.L1_STANDARD_GATEWAY, inbox) + }(address(standardGatewayTemplate), proxyAdmin, bytes("")) ) ); @@ -180,11 +182,9 @@ contract L1AtomicTokenBridgeCreator is Ownable { { L1CustomGateway customGateway = L1CustomGateway( address( - new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_CUSTOM_GATEWAY, inbox) }( - address(customGatewayTemplate), - proxyAdmin, - bytes("") - ) + new TransparentUpgradeableProxy{ + salt: _getL1Salt(OrbitSalts.L1_CUSTOM_GATEWAY, inbox) + }(address(customGatewayTemplate), proxyAdmin, bytes("")) ) ); @@ -197,11 +197,9 @@ contract L1AtomicTokenBridgeCreator is Ownable { L1WethGateway wethGateway = L1WethGateway( payable( address( - new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_WETH_GATEWAY, inbox) }( - address(wethGatewayTemplate), - proxyAdmin, - bytes("") - ) + new TransparentUpgradeableProxy{ + salt: _getL1Salt(OrbitSalts.L1_WETH_GATEWAY, inbox) + }(address(wethGatewayTemplate), proxyAdmin, bytes("")) ) ) ); @@ -233,7 +231,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 maxGas, uint256 gasPriceBid ) internal { - address proxyAdminOwner = msg.sender; + address l2ProxyAdminOwner = _getRollupOwner(inbox); bytes memory data = abi.encodeWithSelector( L2AtomicTokenBridgeFactory.deployL2Contracts.selector, _creationCodeFor(l2RouterTemplate.code), @@ -247,7 +245,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { l1WethGateway, l1Weth, computeExpectedL2StandardGatewayAddress(), - proxyAdminOwner + l2ProxyAdminOwner ); IInbox(inbox).createRetryableTicket{value: maxSubmissionCost + maxGas * gasPriceBid}( @@ -392,6 +390,10 @@ contract L1AtomicTokenBridgeCreator is Ownable { return address(uint160(uint256(keccak256(data)))); } + function _getRollupOwner(address inbox) internal view returns (address) { + return IInbox(inbox).bridge().rollup().owner(); + } + function _getL1Salt(bytes32 prefix, address inbox) internal pure returns (bytes32) { return keccak256(abi.encodePacked(prefix, inbox)); } diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index 42bf597548..a734f246fc 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -2,6 +2,8 @@ import { L1Network, L2Network, getL1Network, getL2Network } from '@arbitrum/sdk' import { JsonRpcProvider } from '@ethersproject/providers' import { BeaconProxyFactory__factory, + IOwnable, + IOwnable__factory, L1CustomGateway, L1CustomGateway__factory, L1ERC20Gateway, @@ -110,7 +112,12 @@ describe('tokenBridge', () => { ) ) + const rollupOwner = await IOwnable__factory.connect( + _l2Network.ethBridge.rollup, + l1Provider + ).owner() await checkOwnership( + rollupOwner.toLowerCase(), ProxyAdmin__factory.connect( _l2Network.tokenBridge.l1ProxyAdmin, l1Provider @@ -329,6 +336,7 @@ async function checkL2WethGatewayInitialization(l2WethGateway: L2WethGateway) { } async function checkOwnership( + rollupOwner: string, l1ProxyAdmin: ProxyAdmin, l2ProxyAdmin: ProxyAdmin, l1Router: L1GatewayRouter, @@ -336,15 +344,10 @@ async function checkOwnership( ) { console.log('checkL2ProxyAdminInitialization') - const l1Owner = await l1ProxyAdmin.owner() - - expect(l1Owner.toLowerCase()).to.be.eq( - (await l2ProxyAdmin.owner()).toLowerCase() - ) - expect(l1Owner.toLowerCase()).to.be.eq((await l1Router.owner()).toLowerCase()) - expect(l1Owner.toLowerCase()).to.be.eq( - (await l1CustomGateway.owner()).toLowerCase() - ) + expect(rollupOwner).to.be.eq((await l1ProxyAdmin.owner()).toLowerCase()) + expect(rollupOwner).to.be.eq((await l2ProxyAdmin.owner()).toLowerCase()) + expect(rollupOwner).to.be.eq((await l1Router.owner()).toLowerCase()) + expect(rollupOwner).to.be.eq((await l1CustomGateway.owner()).toLowerCase()) } export const getProvidersAndSetupNetworks = async (setupConfig: { From d9bc08dacb4d7208bdd6fd0d1a3eb99e3f0a3c58 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jul 2023 11:29:08 +0200 Subject: [PATCH 101/163] Add registry for non-canonical routers --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 04c1c55b4a..4aaa8e4a36 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -20,16 +20,25 @@ import {BeaconProxyFactory, ClonableBeaconProxy} from "../libraries/ClonableBeac * @dev Throughout the contract terms L1 and L2 are used, but those can be considered as base (N) chain and child (N+1) chain */ contract L1AtomicTokenBridgeCreator is Ownable { + error L1AtomicTokenBridgeCreator_OnlyRollupOwner(); + error L1AtomicTokenBridgeCreator_InvalidRouterAddr(); + event OrbitTokenBridgeCreated( address router, address standardGateway, address customGateway, address wethGateway, address proxyAdmin ); event OrbitTokenBridgeTemplatesUpdated(); + event NonCanonicalRouterSet(address indexed inbox, address indexed router); + + // non-canonical router registry + mapping(address => address) public inboxToNonCanonicalRouter; + // L1 logic contracts shared by all token bridges L1GatewayRouter public routerTemplate; L1ERC20Gateway public standardGatewayTemplate; L1CustomGateway public customGatewayTemplate; L1WethGateway public wethGatewayTemplate; + // L2 contracts deployed to L1 as bytecode placeholders address public l2TokenBridgeFactoryTemplate; address public l2RouterTemplate; address public l2StandardGatewayTemplate; @@ -37,8 +46,11 @@ contract L1AtomicTokenBridgeCreator is Ownable { address public l2WethGatewayTemplate; address public l2WethTemplate; + // WETH address on L1 address public l1Weth; + // immutable canonical addresses for L2 contracts + // other canonical addresses (dependent on L2 template implementations) can be fetched through `computeExpectedL2***Address` functions address public immutable expectedL2FactoryAddress; address public immutable expectedL2ProxyAdminAddress; address public immutable expectedL2BeaconProxyFactoryAddress; @@ -124,6 +136,29 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); } + /** + * @notice Rollup owner can override canonical router address by registering other non-canonical router. + */ + function setNonCanonicalRouter(address inbox, address nonCanonicalRouter) external { + if (msg.sender != _getRollupOwner(inbox)) revert L1AtomicTokenBridgeCreator_OnlyRollupOwner(); + if (nonCanonicalRouter == computeExpectedL1RouterAddress(inbox)) { + revert L1AtomicTokenBridgeCreator_InvalidRouterAddr(); + } + + inboxToNonCanonicalRouter[inbox] = nonCanonicalRouter; + emit NonCanonicalRouterSet(inbox, nonCanonicalRouter); + } + + function getRouter(address inbox) public view returns (address) { + address nonCanonicalRouter = inboxToNonCanonicalRouter[inbox]; + + if (nonCanonicalRouter != address(0)) { + return nonCanonicalRouter; + } + + return computeExpectedL1RouterAddress(inbox); + } + function _deployL1Contracts(address inbox, address owner) internal returns (address router, address standardGateway, address customGateway, address wethGateway) @@ -253,6 +288,23 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); } + function computeExpectedL1RouterAddress(address inbox) public view returns (address) { + address expectedL1ProxyAdminAddress = Create2.computeAddress( + _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox), keccak256(type(ProxyAdmin).creationCode), address(this) + ); + + return Create2.computeAddress( + _getL1Salt(OrbitSalts.L1_ROUTER, inbox), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(routerTemplate, expectedL1ProxyAdminAddress, bytes("")) + ) + ), + address(this) + ); + } + function computeExpectedL2RouterAddress() public view returns (address) { address expectedL2RouterLogic = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), From 9bacef0dc27ee98848278788e5e24fe9c5792a96 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jul 2023 11:43:32 +0200 Subject: [PATCH 102/163] Rename computeExpected -> getCanonical --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 8 +- .../ethereum/L1AtomicTokenBridgeCreator.sol | 78 +++++++++---------- .../atomicTokenBridgeDeployer.ts | 10 +-- 3 files changed, 47 insertions(+), 49 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 05c68f82bc..fab8d0c8d6 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -30,14 +30,14 @@ contract L2AtomicTokenBridgeFactory { address l1CustomGateway, address l1WethGateway, address l1Weth, - address l2StandardGatewayExpectedAddress, + address l2StandardGatewayCanonicalAddress, address proxyAdminOwner ) external { // create proxyAdmin which will be used for all contracts address proxyAdmin = address(new ProxyAdmin{ salt: _getL2Salt(OrbitSalts.L2_PROXY_ADMIN) }()); // deploy router/gateways - address router = _deployRouter(routerCreationCode, l1Router, l2StandardGatewayExpectedAddress, proxyAdmin); + address router = _deployRouter(routerCreationCode, l1Router, l2StandardGatewayCanonicalAddress, proxyAdmin); _deployStandardGateway(standardGatewayCreationCode, l1StandardGateway, router, proxyAdmin); _deployCustomGateway(customGatewayCreationCode, l1CustomGateway, router, proxyAdmin); _deployWethGateway(wethGatewayCreationCode, aeWethCreationCode, l1WethGateway, l1Weth, router, proxyAdmin); @@ -49,7 +49,7 @@ contract L2AtomicTokenBridgeFactory { function _deployRouter( bytes memory creationCode, address l1Router, - address l2StandardGatewayExpectedAddress, + address l2StandardGatewayCanonicalAddress, address proxyAdmin ) internal returns (address) { // create logic and proxy @@ -65,7 +65,7 @@ contract L2AtomicTokenBridgeFactory { ); // init - router.initialize(l1Router, l2StandardGatewayExpectedAddress); + router.initialize(l1Router, l2StandardGatewayCanonicalAddress); return address(router); } diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 4aaa8e4a36..295a300991 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -51,21 +51,21 @@ contract L1AtomicTokenBridgeCreator is Ownable { // immutable canonical addresses for L2 contracts // other canonical addresses (dependent on L2 template implementations) can be fetched through `computeExpectedL2***Address` functions - address public immutable expectedL2FactoryAddress; - address public immutable expectedL2ProxyAdminAddress; - address public immutable expectedL2BeaconProxyFactoryAddress; + address public immutable canonicalL2FactoryAddress; + address public immutable canonicalL2ProxyAdminAddress; + address public immutable canonicalL2BeaconProxyFactoryAddress; constructor() Ownable() { - expectedL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); + canonicalL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); - expectedL2ProxyAdminAddress = Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), expectedL2FactoryAddress + canonicalL2ProxyAdminAddress = Create2.computeAddress( + _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), canonicalL2FactoryAddress ); - expectedL2BeaconProxyFactoryAddress = Create2.computeAddress( + canonicalL2BeaconProxyFactoryAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.BEACON_PROXY_FACTORY), keccak256(type(BeaconProxyFactory).creationCode), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); } @@ -141,7 +141,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { */ function setNonCanonicalRouter(address inbox, address nonCanonicalRouter) external { if (msg.sender != _getRollupOwner(inbox)) revert L1AtomicTokenBridgeCreator_OnlyRollupOwner(); - if (nonCanonicalRouter == computeExpectedL1RouterAddress(inbox)) { + if (nonCanonicalRouter == getCanonicalL1RouterAddress(inbox)) { revert L1AtomicTokenBridgeCreator_InvalidRouterAddr(); } @@ -156,7 +156,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { return nonCanonicalRouter; } - return computeExpectedL1RouterAddress(inbox); + return getCanonicalL1RouterAddress(inbox); } function _deployL1Contracts(address inbox, address owner) @@ -181,7 +181,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { // init router L1GatewayRouter(router).initialize( - owner, address(standardGateway), address(0), computeExpectedL2RouterAddress(), inbox + owner, address(standardGateway), address(0), getCanonicalL2RouterAddress(), inbox ); // transfer ownership to owner @@ -201,11 +201,11 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); standardGateway.initialize( - computeExpectedL2StandardGatewayAddress(), + getCanonicalL2StandardGatewayAddress(), router, inbox, keccak256(type(ClonableBeaconProxy).creationCode), - expectedL2BeaconProxyFactoryAddress + canonicalL2BeaconProxyFactoryAddress ); return address(standardGateway); @@ -223,7 +223,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { ) ); - customGateway.initialize(computeExpectedL2CustomGatewayAddress(), router, inbox, owner); + customGateway.initialize(getCanonicalL2CustomGatewayAddress(), router, inbox, owner); return address(customGateway); } @@ -239,9 +239,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { ) ); - wethGateway.initialize( - computeExpectedL2WethGatewayAddress(), router, inbox, l1Weth, computeExpectedL2WethAddress() - ); + wethGateway.initialize(getCanonicalL2WethGatewayAddress(), router, inbox, l1Weth, getCanonicalL2WethAddress()); return address(wethGateway); } @@ -279,16 +277,16 @@ contract L1AtomicTokenBridgeCreator is Ownable { l1CustomGateway, l1WethGateway, l1Weth, - computeExpectedL2StandardGatewayAddress(), + getCanonicalL2StandardGatewayAddress(), l2ProxyAdminOwner ); IInbox(inbox).createRetryableTicket{value: maxSubmissionCost + maxGas * gasPriceBid}( - expectedL2FactoryAddress, 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, data + canonicalL2FactoryAddress, 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, data ); } - function computeExpectedL1RouterAddress(address inbox) public view returns (address) { + function getCanonicalL1RouterAddress(address inbox) public view returns (address) { address expectedL1ProxyAdminAddress = Create2.computeAddress( _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox), keccak256(type(ProxyAdmin).creationCode), address(this) ); @@ -305,11 +303,11 @@ contract L1AtomicTokenBridgeCreator is Ownable { ); } - function computeExpectedL2RouterAddress() public view returns (address) { + function getCanonicalL2RouterAddress() public view returns (address) { address expectedL2RouterLogic = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), keccak256(_creationCodeFor(l2RouterTemplate.code)), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); return Create2.computeAddress( @@ -317,36 +315,36 @@ contract L1AtomicTokenBridgeCreator is Ownable { keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2RouterLogic, expectedL2ProxyAdminAddress, bytes("")) + abi.encode(expectedL2RouterLogic, canonicalL2ProxyAdminAddress, bytes("")) ) ), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); } - function computeExpectedL2StandardGatewayAddress() public view returns (address) { + function getCanonicalL2StandardGatewayAddress() public view returns (address) { address expectedL2StandardGatewayLogic = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), keccak256(_creationCodeFor(l2StandardGatewayTemplate.code)), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); return Create2.computeAddress( _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY), keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2StandardGatewayLogic, expectedL2ProxyAdminAddress, bytes("")) + abi.encode(expectedL2StandardGatewayLogic, canonicalL2ProxyAdminAddress, bytes("")) ) ), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); } - function computeExpectedL2CustomGatewayAddress() public view returns (address) { + function getCanonicalL2CustomGatewayAddress() public view returns (address) { address expectedL2CustomGatewayLogic = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), keccak256(_creationCodeFor(l2CustomGatewayTemplate.code)), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); return Create2.computeAddress( @@ -354,18 +352,18 @@ contract L1AtomicTokenBridgeCreator is Ownable { keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2CustomGatewayLogic, expectedL2ProxyAdminAddress, bytes("")) + abi.encode(expectedL2CustomGatewayLogic, canonicalL2ProxyAdminAddress, bytes("")) ) ), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); } - function computeExpectedL2WethGatewayAddress() public view returns (address) { + function getCanonicalL2WethGatewayAddress() public view returns (address) { address expectedL2WethGatewayLogic = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), keccak256(_creationCodeFor(l2WethGatewayTemplate.code)), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); return Create2.computeAddress( @@ -373,18 +371,18 @@ contract L1AtomicTokenBridgeCreator is Ownable { keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2WethGatewayLogic, expectedL2ProxyAdminAddress, bytes("")) + abi.encode(expectedL2WethGatewayLogic, canonicalL2ProxyAdminAddress, bytes("")) ) ), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); } - function computeExpectedL2WethAddress() public view returns (address) { + function getCanonicalL2WethAddress() public view returns (address) { address expectedL2WethLogic = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_WETH_LOGIC), keccak256(_creationCodeFor(l2WethTemplate.code)), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); return Create2.computeAddress( @@ -392,10 +390,10 @@ contract L1AtomicTokenBridgeCreator is Ownable { keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2WethLogic, expectedL2ProxyAdminAddress, bytes("")) + abi.encode(expectedL2WethLogic, canonicalL2ProxyAdminAddress, bytes("")) ) ), - expectedL2FactoryAddress + canonicalL2FactoryAddress ); } diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 4d6a833d2b..e8dc97c468 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -241,21 +241,21 @@ export const createTokenBridge = async ( )[0].args /// pick up L2 contracts - const l2Router = await l1TokenBridgeCreator.computeExpectedL2RouterAddress() + const l2Router = await l1TokenBridgeCreator.getCanonicalL2RouterAddress() const l2StandardGateway = L2ERC20Gateway__factory.connect( - await l1TokenBridgeCreator.computeExpectedL2StandardGatewayAddress(), + await l1TokenBridgeCreator.getCanonicalL2StandardGatewayAddress(), l2Signer ) const beaconProxyFactory = await l2StandardGateway.beaconProxyFactory() const l2CustomGateway = - await l1TokenBridgeCreator.computeExpectedL2CustomGatewayAddress() + await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress() const l2WethGateway = L2WethGateway__factory.connect( - await l1TokenBridgeCreator.computeExpectedL2WethGatewayAddress(), + await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(), l2Signer ) const l1Weth = await l2WethGateway.l1Weth() const l2Weth = await l2WethGateway.l2Weth() - const l2ProxyAdmin = await l1TokenBridgeCreator.expectedL2ProxyAdminAddress() + const l2ProxyAdmin = await l1TokenBridgeCreator.canonicalL2ProxyAdminAddress() return { l1Router, From 5b500281b929d697b7912e6e3c57dbee69ae4b9f Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jul 2023 13:24:10 +0200 Subject: [PATCH 103/163] Use encodeCall, update event --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 295a300991..2856f27061 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -24,7 +24,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { error L1AtomicTokenBridgeCreator_InvalidRouterAddr(); event OrbitTokenBridgeCreated( - address router, address standardGateway, address customGateway, address wethGateway, address proxyAdmin + address indexed inbox, + address indexed owner, + address router, + address standardGateway, + address customGateway, + address wethGateway, + address proxyAdmin ); event OrbitTokenBridgeTemplatesUpdated(); event NonCanonicalRouterSet(address indexed inbox, address indexed router); @@ -138,6 +144,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { /** * @notice Rollup owner can override canonical router address by registering other non-canonical router. + * @dev Non-canonical router can be unregistered by re-setting it to address(0) - it makes canonical router the valid one. */ function setNonCanonicalRouter(address inbox, address nonCanonicalRouter) external { if (msg.sender != _getRollupOwner(inbox)) revert L1AtomicTokenBridgeCreator_OnlyRollupOwner(); @@ -188,7 +195,7 @@ contract L1AtomicTokenBridgeCreator is Ownable { ProxyAdmin(proxyAdmin).transferOwnership(owner); // emit it - emit OrbitTokenBridgeCreated(router, standardGateway, customGateway, wethGateway, proxyAdmin); + emit OrbitTokenBridgeCreated(inbox, owner, router, standardGateway, customGateway, wethGateway, proxyAdmin); } function _deployL1StandardGateway(address proxyAdmin, address router, address inbox) internal returns (address) { @@ -265,20 +272,22 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 gasPriceBid ) internal { address l2ProxyAdminOwner = _getRollupOwner(inbox); - bytes memory data = abi.encodeWithSelector( - L2AtomicTokenBridgeFactory.deployL2Contracts.selector, - _creationCodeFor(l2RouterTemplate.code), - _creationCodeFor(l2StandardGatewayTemplate.code), - _creationCodeFor(l2CustomGatewayTemplate.code), - _creationCodeFor(l2WethGatewayTemplate.code), - _creationCodeFor(l2WethTemplate.code), - l1Router, - l1StandardGateway, - l1CustomGateway, - l1WethGateway, - l1Weth, - getCanonicalL2StandardGatewayAddress(), - l2ProxyAdminOwner + bytes memory data = abi.encodeCall( + L2AtomicTokenBridgeFactory.deployL2Contracts, + ( + _creationCodeFor(l2RouterTemplate.code), + _creationCodeFor(l2StandardGatewayTemplate.code), + _creationCodeFor(l2CustomGatewayTemplate.code), + _creationCodeFor(l2WethGatewayTemplate.code), + _creationCodeFor(l2WethTemplate.code), + l1Router, + l1StandardGateway, + l1CustomGateway, + l1WethGateway, + l1Weth, + getCanonicalL2StandardGatewayAddress(), + l2ProxyAdminOwner + ) ); IInbox(inbox).createRetryableTicket{value: maxSubmissionCost + maxGas * gasPriceBid}( From b68888a43672581c4f39d848e137b4fa232c03c2 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jul 2023 13:49:20 +0200 Subject: [PATCH 104/163] Use struct for L2 bytecode --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 57 +++++++++++-------- .../ethereum/L1AtomicTokenBridgeCreator.sol | 19 ++++--- .../atomicTokenBridgeDeployer.ts | 13 +++-- 3 files changed, 54 insertions(+), 35 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index fab8d0c8d6..2c88afb758 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -20,34 +20,30 @@ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; */ contract L2AtomicTokenBridgeFactory { function deployL2Contracts( - bytes memory routerCreationCode, - bytes memory standardGatewayCreationCode, - bytes memory customGatewayCreationCode, - bytes memory wethGatewayCreationCode, - bytes memory aeWethCreationCode, + L2CreationCode calldata l2Code, address l1Router, address l1StandardGateway, address l1CustomGateway, address l1WethGateway, address l1Weth, address l2StandardGatewayCanonicalAddress, - address proxyAdminOwner + address rollupOwner ) external { // create proxyAdmin which will be used for all contracts address proxyAdmin = address(new ProxyAdmin{ salt: _getL2Salt(OrbitSalts.L2_PROXY_ADMIN) }()); // deploy router/gateways - address router = _deployRouter(routerCreationCode, l1Router, l2StandardGatewayCanonicalAddress, proxyAdmin); - _deployStandardGateway(standardGatewayCreationCode, l1StandardGateway, router, proxyAdmin); - _deployCustomGateway(customGatewayCreationCode, l1CustomGateway, router, proxyAdmin); - _deployWethGateway(wethGatewayCreationCode, aeWethCreationCode, l1WethGateway, l1Weth, router, proxyAdmin); + address router = _deployRouter(l2Code.router, l1Router, l2StandardGatewayCanonicalAddress, proxyAdmin); + _deployStandardGateway(l2Code.standardGateway, l1StandardGateway, router, proxyAdmin); + _deployCustomGateway(l2Code.customGateway, l1CustomGateway, router, proxyAdmin); + _deployWethGateway(l2Code.wethGateway, l2Code.aeWeth, l1WethGateway, l1Weth, router, proxyAdmin); - // transfer ownership to L1Creator's msg.sender - ProxyAdmin(proxyAdmin).transferOwnership(proxyAdminOwner); + // transfer ownership to rollup's owner + ProxyAdmin(proxyAdmin).transferOwnership(rollupOwner); } function _deployRouter( - bytes memory creationCode, + bytes calldata creationCode, address l1Router, address l2StandardGatewayCanonicalAddress, address proxyAdmin @@ -71,7 +67,7 @@ contract L2AtomicTokenBridgeFactory { } function _deployStandardGateway( - bytes memory creationCode, + bytes calldata creationCode, address l1StandardGateway, address router, address proxyAdmin @@ -81,9 +77,11 @@ contract L2AtomicTokenBridgeFactory { Create2.deploy(0, _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), creationCode); L2ERC20Gateway standardGateway = L2ERC20Gateway( address( - new TransparentUpgradeableProxy{ - salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY) - }(standardGatewayLogicAddress, proxyAdmin, bytes("")) + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY) }( + standardGatewayLogicAddress, + proxyAdmin, + bytes("") + ) ) ); @@ -104,7 +102,7 @@ contract L2AtomicTokenBridgeFactory { } function _deployCustomGateway( - bytes memory creationCode, + bytes calldata creationCode, address l1CustomGateway, address router, address proxyAdmin @@ -128,8 +126,8 @@ contract L2AtomicTokenBridgeFactory { } function _deployWethGateway( - bytes memory wethGatewayCreationCode, - bytes memory aeWethCreationCode, + bytes calldata wethGatewayCreationCode, + bytes calldata aeWethCreationCode, address l1WethGateway, address l1Weth, address router, @@ -155,9 +153,11 @@ contract L2AtomicTokenBridgeFactory { L2WethGateway wethGateway = L2WethGateway( payable( address( - new TransparentUpgradeableProxy{ - salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY) - }(wethGatewayLogicAddress, proxyAdmin, bytes("")) + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY) }( + wethGatewayLogicAddress, + proxyAdmin, + bytes("") + ) ) ) ); @@ -174,6 +174,17 @@ contract L2AtomicTokenBridgeFactory { } } +/** + * Placeholder for bytecode of token bridge contracts which is sent from L1 to L2 through retryable ticket. + */ +struct L2CreationCode { + bytes router; + bytes standardGateway; + bytes customGateway; + bytes wethGateway; + bytes aeWeth; +} + /** * Collection of salts used in CREATE2 deployment of L2 token bridge contracts. */ diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 2856f27061..4b25ecce72 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -7,7 +7,7 @@ import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; import {L1WethGateway} from "./gateway/L1WethGateway.sol"; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import {L2AtomicTokenBridgeFactory, OrbitSalts} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; +import {L2AtomicTokenBridgeFactory, OrbitSalts, L2CreationCode} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; @@ -147,7 +147,9 @@ contract L1AtomicTokenBridgeCreator is Ownable { * @dev Non-canonical router can be unregistered by re-setting it to address(0) - it makes canonical router the valid one. */ function setNonCanonicalRouter(address inbox, address nonCanonicalRouter) external { - if (msg.sender != _getRollupOwner(inbox)) revert L1AtomicTokenBridgeCreator_OnlyRollupOwner(); + if (msg.sender != _getRollupOwner(inbox)) { + revert L1AtomicTokenBridgeCreator_OnlyRollupOwner(); + } if (nonCanonicalRouter == getCanonicalL1RouterAddress(inbox)) { revert L1AtomicTokenBridgeCreator_InvalidRouterAddr(); } @@ -272,14 +274,17 @@ contract L1AtomicTokenBridgeCreator is Ownable { uint256 gasPriceBid ) internal { address l2ProxyAdminOwner = _getRollupOwner(inbox); + L2CreationCode memory l2Code = L2CreationCode( + _creationCodeFor(l2RouterTemplate.code), + _creationCodeFor(l2StandardGatewayTemplate.code), + _creationCodeFor(l2CustomGatewayTemplate.code), + _creationCodeFor(l2WethGatewayTemplate.code), + _creationCodeFor(l2WethTemplate.code) + ); bytes memory data = abi.encodeCall( L2AtomicTokenBridgeFactory.deployL2Contracts, ( - _creationCodeFor(l2RouterTemplate.code), - _creationCodeFor(l2StandardGatewayTemplate.code), - _creationCodeFor(l2CustomGatewayTemplate.code), - _creationCodeFor(l2WethGatewayTemplate.code), - _creationCodeFor(l2WethTemplate.code), + l2Code, l1Router, l1StandardGateway, l1CustomGateway, diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index e8dc97c468..5b570b8832 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -155,13 +155,16 @@ export const createTokenBridge = async ( await l1TokenBridgeCreator.l2TokenBridgeFactoryTemplate(), l1Signer ) + const l2Code = { + router: L2GatewayRouter__factory.bytecode, + standardGateway: L2ERC20Gateway__factory.bytecode, + customGateway: L2CustomGateway__factory.bytecode, + wethGateway: L2WethGateway__factory.bytecode, + aeWeth: AeWETH__factory.bytecode, + } const gasEstimateToDeployContracts = await l2FactoryTemplate.estimateGas.deployL2Contracts( - L2GatewayRouter__factory.bytecode, - L2ERC20Gateway__factory.bytecode, - L2CustomGateway__factory.bytecode, - L2WethGateway__factory.bytecode, - AeWETH__factory.bytecode, + l2Code, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, From b5275ba66aff8ccceb9ff50113f0032daf530ce1 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 6 Jul 2023 18:07:38 +0200 Subject: [PATCH 105/163] Calculate maxSubmissionCost dynamically and refund the excess --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 47 ++++++++++--------- .../atomicTokenBridgeDeployer.ts | 2 - 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 4b25ecce72..6ce8a83f2c 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -22,6 +22,8 @@ import {BeaconProxyFactory, ClonableBeaconProxy} from "../libraries/ClonableBeac contract L1AtomicTokenBridgeCreator is Ownable { error L1AtomicTokenBridgeCreator_OnlyRollupOwner(); error L1AtomicTokenBridgeCreator_InvalidRouterAddr(); + error L1AtomicTokenBridgeCreator_RefundFailed(); + error L1AtomicTokenBridgeCreator_TemplatesNotSet(); event OrbitTokenBridgeCreated( address indexed inbox, @@ -116,30 +118,25 @@ contract L1AtomicTokenBridgeCreator is Ownable { * 2 retryable tickets to deploy L2 side. 1st one deploy L2 factory and 2nd calls function that deploys and inits * all the rest of the contracts. L2 chain is determined by `inbox` parameter. */ - function createTokenBridge( - address inbox, - uint256 maxSubmissionCostForFactory, - uint256 maxGasForFactory, - uint256 maxSubmissionCostForContracts, - uint256 maxGasForContracts, - uint256 gasPriceBid - ) external payable { + function createTokenBridge(address inbox, uint256 maxGasForFactory, uint256 maxGasForContracts, uint256 gasPriceBid) + external + payable + { + if (address(routerTemplate) == address(0)) revert L1AtomicTokenBridgeCreator_TemplatesNotSet(); address owner = _getRollupOwner(inbox); (address router, address standardGateway, address customGateway, address wethGateway) = _deployL1Contracts(inbox, owner); /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls - _deployL2Factory(inbox, maxSubmissionCostForFactory, maxGasForFactory, gasPriceBid); - _deployL2Contracts( - router, - standardGateway, - customGateway, - wethGateway, - inbox, - maxSubmissionCostForContracts, - maxGasForContracts, - gasPriceBid + uint256 valueSpentForFactory = _deployL2Factory(inbox, maxGasForFactory, gasPriceBid); + uint256 valueSpentForContracts = _deployL2Contracts( + router, standardGateway, customGateway, wethGateway, inbox, maxGasForContracts, gasPriceBid ); + + // refund excess value to the sender + uint256 refund = msg.value - (valueSpentForFactory + valueSpentForContracts); + (bool success,) = msg.sender.call{value: refund}(""); + if (!success) revert L1AtomicTokenBridgeCreator_RefundFailed(); } /** @@ -253,14 +250,17 @@ contract L1AtomicTokenBridgeCreator is Ownable { return address(wethGateway); } - function _deployL2Factory(address inbox, uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid) internal { + function _deployL2Factory(address inbox, uint256 maxGas, uint256 gasPriceBid) internal returns (uint256) { // encode L2 factory bytecode bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); + uint256 maxSubmissionCost = IInbox(inbox).calculateRetryableSubmissionFee(deploymentData.length, 0); uint256 value = maxSubmissionCost + maxGas * gasPriceBid; IInbox(inbox).createRetryableTicket{value: value}( address(0), 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, deploymentData ); + + return value; } function _deployL2Contracts( @@ -269,10 +269,9 @@ contract L1AtomicTokenBridgeCreator is Ownable { address l1CustomGateway, address l1WethGateway, address inbox, - uint256 maxSubmissionCost, uint256 maxGas, uint256 gasPriceBid - ) internal { + ) internal returns (uint256) { address l2ProxyAdminOwner = _getRollupOwner(inbox); L2CreationCode memory l2Code = L2CreationCode( _creationCodeFor(l2RouterTemplate.code), @@ -295,9 +294,13 @@ contract L1AtomicTokenBridgeCreator is Ownable { ) ); - IInbox(inbox).createRetryableTicket{value: maxSubmissionCost + maxGas * gasPriceBid}( + uint256 maxSubmissionCost = IInbox(inbox).calculateRetryableSubmissionFee(data.length, 0); + uint256 value = maxSubmissionCost + maxGas * gasPriceBid; + IInbox(inbox).createRetryableTicket{value: value}( canonicalL2FactoryAddress, 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, data ); + + return value; } function getCanonicalL1RouterAddress(address inbox) public view returns (address) { diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 5b570b8832..6b1f4b96f7 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -188,9 +188,7 @@ export const createTokenBridge = async ( const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( inboxAddress, - deployFactoryGasParams.maxSubmissionCost, deployFactoryGasParams.gasLimit, - maxSubmissionCostForContracts, maxGasForContracts, gasPrice, { value: retryableValue } From a922cae2da712fa3f02b15a975f2ea434a74f87d Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 7 Jul 2023 13:52:55 +0200 Subject: [PATCH 106/163] Make L1 creator upgradeable --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 24 ++++-- .../atomicTokenBridgeDeployer.ts | 84 +++++++++++-------- 2 files changed, 62 insertions(+), 46 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 6ce8a83f2c..3e81d85209 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -8,18 +8,18 @@ import {L1WethGateway} from "./gateway/L1WethGateway.sol"; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {L2AtomicTokenBridgeFactory, OrbitSalts, L2CreationCode} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; import {BeaconProxyFactory, ClonableBeaconProxy} from "../libraries/ClonableBeaconProxy.sol"; +import {Initializable, OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; /** * @title Layer1 token bridge creator * @notice This contract is used to deploy token bridge on custom L2 chains. * @dev Throughout the contract terms L1 and L2 are used, but those can be considered as base (N) chain and child (N+1) chain */ -contract L1AtomicTokenBridgeCreator is Ownable { +contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { error L1AtomicTokenBridgeCreator_OnlyRollupOwner(); error L1AtomicTokenBridgeCreator_InvalidRouterAddr(); error L1AtomicTokenBridgeCreator_RefundFailed(); @@ -59,17 +59,21 @@ contract L1AtomicTokenBridgeCreator is Ownable { // immutable canonical addresses for L2 contracts // other canonical addresses (dependent on L2 template implementations) can be fetched through `computeExpectedL2***Address` functions - address public immutable canonicalL2FactoryAddress; - address public immutable canonicalL2ProxyAdminAddress; - address public immutable canonicalL2BeaconProxyFactoryAddress; + address public canonicalL2FactoryAddress; + address public canonicalL2ProxyAdminAddress; + address public canonicalL2BeaconProxyFactoryAddress; - constructor() Ownable() { - canonicalL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); + constructor() { + _disableInitializers(); + } + + function initialize() public initializer { + __Ownable_init(); + canonicalL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); canonicalL2ProxyAdminAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), canonicalL2FactoryAddress ); - canonicalL2BeaconProxyFactoryAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.BEACON_PROXY_FACTORY), keccak256(type(BeaconProxyFactory).creationCode), @@ -122,7 +126,9 @@ contract L1AtomicTokenBridgeCreator is Ownable { external payable { - if (address(routerTemplate) == address(0)) revert L1AtomicTokenBridgeCreator_TemplatesNotSet(); + if (address(routerTemplate) == address(0)) { + revert L1AtomicTokenBridgeCreator_TemplatesNotSet(); + } address owner = _getRollupOwner(inbox); (address router, address standardGateway, address customGateway, address wethGateway) = _deployL1Contracts(inbox, owner); diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 6b1f4b96f7..d1a6c64d7f 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -12,6 +12,7 @@ import { L2WethGateway__factory, AeWETH__factory, L1WethGateway__factory, + TransparentUpgradeableProxy__factory, } from '../../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { @@ -42,15 +43,24 @@ import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' * @param l2Url * @returns */ -export const setupTokenBridgeInLocalEnv = async ( - l1Deployer: Signer, - l2Deployer: Signer, - l1Url: string, - l2Url: string -) => { +export const setupTokenBridgeInLocalEnv = async () => { + /// setup deployers, load local networks + const config = { + arbUrl: 'http://localhost:8547', + ethUrl: 'http://localhost:8545', + } + const l1Deployer = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + new ethers.providers.JsonRpcProvider(config.ethUrl) + ) + const l2Deployer = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + new ethers.providers.JsonRpcProvider(config.arbUrl) + ) + const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( - l1Url, - l2Url + config.ethUrl, + config.arbUrl ) // register - needed for retryables @@ -79,7 +89,13 @@ export const setupTokenBridgeInLocalEnv = async ( }) // prerequisite - deploy L1 creator and set templates - const l1TokenBridgeCreator = await deployL1TokenBridgeCreator(l1Deployer) + const l1TokenBridgeCreatorOwner = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user_b')) + ) + const l1TokenBridgeCreator = await deployL1TokenBridgeCreator( + l1Deployer, + l1TokenBridgeCreatorOwner.address + ) console.log('L1TokenBridgeCreator', l1TokenBridgeCreator.address) // create token bridge @@ -275,12 +291,28 @@ export const createTokenBridge = async ( } } -const deployL1TokenBridgeCreator = async (l1Signer: Signer) => { - /// deploy factory - const l1TokenBridgeCreator = await new L1AtomicTokenBridgeCreator__factory( +const deployL1TokenBridgeCreator = async ( + l1Signer: Signer, + l1CreatorOwner: string +) => { + /// deploy creator behind proxy + const l1TokenBridgeCreatorLogic = + await new L1AtomicTokenBridgeCreator__factory(l1Signer).deploy() + await l1TokenBridgeCreatorLogic.deployed() + + const l1TokenBridgeCreatorProxy = + await new TransparentUpgradeableProxy__factory(l1Signer).deploy( + l1TokenBridgeCreatorLogic.address, + l1CreatorOwner, + '0x' + ) + await l1TokenBridgeCreatorProxy.deployed() + + const l1TokenBridgeCreator = L1AtomicTokenBridgeCreator__factory.connect( + l1TokenBridgeCreatorProxy.address, l1Signer - ).deploy() - await l1TokenBridgeCreator.deployed() + ) + await (await l1TokenBridgeCreator.initialize()).wait() /// deploy L1 logic contracts const routerTemplate = await new L1GatewayRouter__factory(l1Signer).deploy() @@ -454,29 +486,7 @@ export function sleep(ms: number) { } async function main() { - const config = { - arbUrl: 'http://localhost:8547', - ethUrl: 'http://localhost:8545', - } - - const l1Provider = new ethers.providers.JsonRpcProvider(config.ethUrl) - const l2Provider = new ethers.providers.JsonRpcProvider(config.arbUrl) - - const l1DeployerWallet = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - l1Provider - ) - const l2DeployerWallet = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - l2Provider - ) - - const { l1Network, l2Network } = await setupTokenBridgeInLocalEnv( - l1DeployerWallet, - l2DeployerWallet, - config.ethUrl, - config.arbUrl - ) + const { l1Network, l2Network } = await setupTokenBridgeInLocalEnv() const NETWORK_FILE = 'network.json' fs.writeFileSync( From 29f119db7c156302c710e523484f3fd162404d6b Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Sat, 8 Jul 2023 12:05:16 +0200 Subject: [PATCH 107/163] Use dummy logic as create2 address seed --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 121 ++++++++++-------- .../ethereum/L1AtomicTokenBridgeCreator.sol | 38 +++--- .../atomicTokenBridgeDeployer.ts | 4 +- 3 files changed, 89 insertions(+), 74 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 2c88afb758..fbaf730d1f 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -10,7 +10,10 @@ import {BeaconProxyFactory} from "../libraries/ClonableBeaconProxy.sol"; import {aeWETH} from "../libraries/aeWETH.sol"; import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import { + TransparentUpgradeableProxy, + ITransparentUpgradeableProxy +} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; /** @@ -48,22 +51,23 @@ contract L2AtomicTokenBridgeFactory { address l2StandardGatewayCanonicalAddress, address proxyAdmin ) internal returns (address) { - // create logic and proxy - address routerLogicAddress = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), creationCode); - L2GatewayRouter router = L2GatewayRouter( - address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_ROUTER) }( - routerLogicAddress, - proxyAdmin, - bytes("") - ) + // canonical L2 router with dummy logic + address canonicalRouter = address( + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_ROUTER) }( + address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC)}()), + proxyAdmin, + bytes("") ) ); + // create L2 router logic and upgrade + address routerLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), creationCode); + ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalRouter), routerLogic); + // init - router.initialize(l1Router, l2StandardGatewayCanonicalAddress); + L2GatewayRouter(canonicalRouter).initialize(l1Router, l2StandardGatewayCanonicalAddress); - return address(router); + return canonicalRouter; } function _deployStandardGateway( @@ -72,19 +76,19 @@ contract L2AtomicTokenBridgeFactory { address router, address proxyAdmin ) internal { - // create logic and proxy - address standardGatewayLogicAddress = - Create2.deploy(0, _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), creationCode); - L2ERC20Gateway standardGateway = L2ERC20Gateway( - address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY) }( - standardGatewayLogicAddress, - proxyAdmin, - bytes("") - ) + // canonical L2 standard gateway with dummy logic + address canonicalStdGateway = address( + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY) }( + address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC)}()), + proxyAdmin, + bytes("") ) ); + // create L2 standard gateway logic and upgrade + address stdGatewayLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), creationCode); + ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalStdGateway), stdGatewayLogic); + // create beacon StandardArbERC20 standardArbERC20 = new StandardArbERC20{ salt: _getL2Salt(OrbitSalts.L2_STANDARD_ERC20) @@ -98,7 +102,7 @@ contract L2AtomicTokenBridgeFactory { // init contracts beaconProxyFactory.initialize(address(beacon)); - standardGateway.initialize(l1StandardGateway, router, address(beaconProxyFactory)); + L2ERC20Gateway(canonicalStdGateway).initialize(l1StandardGateway, router, address(beaconProxyFactory)); } function _deployCustomGateway( @@ -107,22 +111,22 @@ contract L2AtomicTokenBridgeFactory { address router, address proxyAdmin ) internal { - address customGatewayLogicAddress = - Create2.deploy(0, _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), creationCode); - - // create logic and proxy - L2CustomGateway customGateway = L2CustomGateway( - address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY) }( - customGatewayLogicAddress, - proxyAdmin, - bytes("") - ) + // canonical L2 custom gateway with dummy logic + address canonicalCustomGateway = address( + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY) }( + address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC)}()), + proxyAdmin, + bytes("") ) ); + // create L2 custom gateway logic and upgrade + address customGatewayLogicAddress = + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), creationCode); + ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalCustomGateway), customGatewayLogicAddress); + // init - customGateway.initialize(l1CustomGateway, router); + L2GatewayRouter(canonicalCustomGateway).initialize(l1CustomGateway, router); } function _deployWethGateway( @@ -133,40 +137,40 @@ contract L2AtomicTokenBridgeFactory { address router, address proxyAdmin ) internal { - // L2 WETH - address aeWethLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_LOGIC), aeWethCreationCode); - aeWETH l2Weth = aeWETH( - payable( - address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH) }( - aeWethLogic, + // canonical L2 WETH with dummy logic + address canonicalL2Weth = address( + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH) }( + address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_WETH_LOGIC)}()), proxyAdmin, bytes("") ) - ) - ) ); - // WETH gateway - address wethGatewayLogicAddress = - Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), wethGatewayCreationCode); - L2WethGateway wethGateway = L2WethGateway( - payable( - address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY) }( - wethGatewayLogicAddress, + // create L2WETH logic and upgrade + address l2WethLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_LOGIC), aeWethCreationCode); + ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalL2Weth), l2WethLogic); + + // canonical L2 WETH gateway with dummy logic + address canonicalL2WethGateway = address( + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY) }( + address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC)}()), proxyAdmin, bytes("") ) - ) - ) ); + // create L2WETH gateway logic and upgrade + address l2WethGatewayLogic = + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), wethGatewayCreationCode); + ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalL2WethGateway), l2WethGatewayLogic); + // init gateway - wethGateway.initialize(l1WethGateway, router, l1Weth, address(l2Weth)); + L2WethGateway(payable(canonicalL2WethGateway)).initialize( + l1WethGateway, router, l1Weth, address(canonicalL2Weth) + ); // init L2Weth - l2Weth.initialize("WETH", "WETH", 18, address(wethGateway), l1Weth); + aeWETH(payable(canonicalL2Weth)).initialize("WETH", "WETH", 18, canonicalL2WethGateway, l1Weth); } function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { @@ -174,6 +178,11 @@ contract L2AtomicTokenBridgeFactory { } } +/** + * Dummy contract used as initial logic contract for proxies, in order to get canonical (CREATE2 based) address. Then we can upgrade to any logic without having canonical addresses impacted. + */ +contract CanonicalAddressSeed {} + /** * Placeholder for bytecode of token bridge contracts which is sent from L1 to L2 through retryable ticket. */ diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 3e81d85209..f00b40254f 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -7,7 +7,12 @@ import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; import {L1WethGateway} from "./gateway/L1WethGateway.sol"; import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import {L2AtomicTokenBridgeFactory, OrbitSalts, L2CreationCode} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; +import { + L2AtomicTokenBridgeFactory, + CanonicalAddressSeed, + OrbitSalts, + L2CreationCode +} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; @@ -327,9 +332,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function getCanonicalL2RouterAddress() public view returns (address) { - address expectedL2RouterLogic = Create2.computeAddress( + address logicSeedAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), - keccak256(_creationCodeFor(l2RouterTemplate.code)), + keccak256(type(CanonicalAddressSeed).creationCode), canonicalL2FactoryAddress ); @@ -338,7 +343,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2RouterLogic, canonicalL2ProxyAdminAddress, bytes("")) + abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) ) ), canonicalL2FactoryAddress @@ -346,17 +351,18 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function getCanonicalL2StandardGatewayAddress() public view returns (address) { - address expectedL2StandardGatewayLogic = Create2.computeAddress( + address logicSeedAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), - keccak256(_creationCodeFor(l2StandardGatewayTemplate.code)), + keccak256(type(CanonicalAddressSeed).creationCode), canonicalL2FactoryAddress ); + return Create2.computeAddress( _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY), keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2StandardGatewayLogic, canonicalL2ProxyAdminAddress, bytes("")) + abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) ) ), canonicalL2FactoryAddress @@ -364,9 +370,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function getCanonicalL2CustomGatewayAddress() public view returns (address) { - address expectedL2CustomGatewayLogic = Create2.computeAddress( + address logicSeedAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), - keccak256(_creationCodeFor(l2CustomGatewayTemplate.code)), + keccak256(type(CanonicalAddressSeed).creationCode), canonicalL2FactoryAddress ); @@ -375,7 +381,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2CustomGatewayLogic, canonicalL2ProxyAdminAddress, bytes("")) + abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) ) ), canonicalL2FactoryAddress @@ -383,9 +389,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function getCanonicalL2WethGatewayAddress() public view returns (address) { - address expectedL2WethGatewayLogic = Create2.computeAddress( + address logicSeedAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), - keccak256(_creationCodeFor(l2WethGatewayTemplate.code)), + keccak256(type(CanonicalAddressSeed).creationCode), canonicalL2FactoryAddress ); @@ -394,7 +400,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2WethGatewayLogic, canonicalL2ProxyAdminAddress, bytes("")) + abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) ) ), canonicalL2FactoryAddress @@ -402,9 +408,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function getCanonicalL2WethAddress() public view returns (address) { - address expectedL2WethLogic = Create2.computeAddress( + address logicSeedAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_WETH_LOGIC), - keccak256(_creationCodeFor(l2WethTemplate.code)), + keccak256(type(CanonicalAddressSeed).creationCode), canonicalL2FactoryAddress ); @@ -413,7 +419,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(expectedL2WethLogic, canonicalL2ProxyAdminAddress, bytes("")) + abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) ) ), canonicalL2FactoryAddress diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index d1a6c64d7f..cebd11169e 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -270,8 +270,8 @@ export const createTokenBridge = async ( await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(), l2Signer ) - const l1Weth = await l2WethGateway.l1Weth() - const l2Weth = await l2WethGateway.l2Weth() + const l1Weth = await l1TokenBridgeCreator.l1Weth() + const l2Weth = await l1TokenBridgeCreator.getCanonicalL2WethAddress() const l2ProxyAdmin = await l1TokenBridgeCreator.canonicalL2ProxyAdminAddress() return { From 267e19f45b3985b1a38271c2e6adab7361258437 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 10 Jul 2023 09:30:53 +0200 Subject: [PATCH 108/163] Add token bridge deployment test to CI --- .github/workflows/build-test.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index ab21f04339..e752ab876b 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -28,3 +28,29 @@ jobs: - name: Test Storage Layouts run: yarn run test:storage + test-token-bridge-deployer: + name: Test hardhat + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Setup node/yarn + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'yarn' + cache-dependency-path: '**/yarn.lock' + + - name: Install packages + run: yarn + + - name: Compile contracts + run: yarn build + + - name: Deploy token bridge + run: yarn run deploy:tokenbridge:atomic + + - name: Test token bridge deployment + run: yarn run test:tokenbridge:deployment \ No newline at end of file From 5d451b2e0901e36ac51a181577a7054de2489c29 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 10 Jul 2023 09:47:16 +0200 Subject: [PATCH 109/163] Match sequencer container using regex --- .github/workflows/build-test.yml | 2 +- .../atomicTokenBridgeDeployer.ts | 20 ++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index e752ab876b..25f17c0c0a 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -29,7 +29,7 @@ jobs: - name: Test Storage Layouts run: yarn run test:storage test-token-bridge-deployer: - name: Test hardhat + name: Test token bridge deployment runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index cebd11169e..1a3bcfb83a 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -393,15 +393,17 @@ export const getLocalNetworks = async ( const l1Provider = new JsonRpcProvider(l1Url) const l2Provider = new JsonRpcProvider(l2Url) let deploymentData: string - try { - deploymentData = execSync( - 'docker exec nitro_testnode_sequencer_1 cat /config/deployment.json' - ).toString() - } catch (e) { - deploymentData = execSync( - 'docker exec nitro-testnode-sequencer-1 cat /config/deployment.json' - ).toString() - } + + let sequencerContainer = execSync( + 'docker ps --filter "name=sequencer" --format "{{.Names}}"' + ) + .toString() + .trim() + + deploymentData = execSync( + `docker exec ${sequencerContainer} cat /config/deployment.json` + ).toString() + const parsedDeploymentData = JSON.parse(deploymentData) as { bridge: string inbox: string From 522223a348df660fe44de3e092800b1ce135d22f Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 10 Jul 2023 10:43:09 +0200 Subject: [PATCH 110/163] Fix CI --- .github/workflows/build-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 25f17c0c0a..14076ca8e9 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -35,6 +35,7 @@ jobs: - uses: actions/checkout@v3 with: submodules: recursive + - uses: OffchainLabs/actions/run-nitro-test-node@main - name: Setup node/yarn uses: actions/setup-node@v3 From a00f2694a88a9ecf14efe2e302b7f2f50baa0138 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 10 Jul 2023 10:55:50 +0200 Subject: [PATCH 111/163] Remove factories that use 3-TX deployment of token bridge --- .../arbitrum/L2TokenBridgeFactory.sol | 45 ----------- .../ethereum/L1TokenBridgeCreator.sol | 75 ------------------- package.json | 1 - 3 files changed, 121 deletions(-) delete mode 100644 contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol delete mode 100644 contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol diff --git a/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol deleted file mode 100644 index 08c04a125a..0000000000 --- a/contracts/tokenbridge/arbitrum/L2TokenBridgeFactory.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.0; - -import {L2GatewayRouter} from "./gateway/L2GatewayRouter.sol"; -import {L2ERC20Gateway} from "./gateway/L2ERC20Gateway.sol"; -import {L2CustomGateway} from "./gateway/L2CustomGateway.sol"; -import {StandardArbERC20} from "./StandardArbERC20.sol"; -import {BeaconProxyFactory} from "../libraries/ClonableBeaconProxy.sol"; -import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; -import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; - -contract L2TokenBridgeFactory { - event OrbitL2TokenBridgeCreated( - address router, address standardGateway, address customGateway, address beaconProxyFactory, address proxyAdmin - ); - - constructor(address l1Router, address l1StandardGateway, address l1CustomGateway) { - address proxyAdmin = address(new ProxyAdmin()); - - // create router/gateways - L2GatewayRouter router = L2GatewayRouter(_deployBehindProxy(address(new L2GatewayRouter()), proxyAdmin)); - L2ERC20Gateway standardGateway = L2ERC20Gateway(_deployBehindProxy(address(new L2ERC20Gateway()), proxyAdmin)); - L2CustomGateway customGateway = L2CustomGateway(_deployBehindProxy(address(new L2CustomGateway()), proxyAdmin)); - - // create beacon - StandardArbERC20 standardArbERC20 = new StandardArbERC20(); - UpgradeableBeacon beacon = new UpgradeableBeacon(address(standardArbERC20)); - BeaconProxyFactory beaconProxyFactory = new BeaconProxyFactory(); - - // init contracts - router.initialize(l1Router, address(standardGateway)); - beaconProxyFactory.initialize(address(beacon)); - standardGateway.initialize(l1StandardGateway, address(router), address(beaconProxyFactory)); - customGateway.initialize(l1CustomGateway, address(router)); - - emit OrbitL2TokenBridgeCreated( - address(router), address(standardGateway), address(customGateway), address(beaconProxyFactory), proxyAdmin - ); - } - - function _deployBehindProxy(address logic, address proxyAdmin) internal returns (address) { - return address(new TransparentUpgradeableProxy(logic, proxyAdmin, bytes(""))); - } -} diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol deleted file mode 100644 index 301e2c37b9..0000000000 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeCreator.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.0; - -import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol"; -import {L1ERC20Gateway} from "./gateway/L1ERC20Gateway.sol"; -import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; -import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; -import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; - -contract L1TokenBridgeCreator is Ownable { - event OrbitTokenBridgeCreated(address router, address standardGateway, address customGateway, address proxyAdmin); - event OrbitTokenBridgeTemplatesUpdated(); - - L1GatewayRouter public routerTemplate; - L1ERC20Gateway public standardGatewayTemplate; - L1CustomGateway public customGatewayTemplate; - - constructor() Ownable() {} - - function setTemplates(L1GatewayRouter _router, L1ERC20Gateway _standardGateway, L1CustomGateway _customGateway) - external - onlyOwner - { - routerTemplate = _router; - standardGatewayTemplate = _standardGateway; - customGatewayTemplate = _customGateway; - emit OrbitTokenBridgeTemplatesUpdated(); - } - - function createTokenBridge() external { - address proxyAdmin = address(new ProxyAdmin()); - - L1GatewayRouter router = - L1GatewayRouter(address(new TransparentUpgradeableProxy(address(routerTemplate), proxyAdmin, bytes("")))); - L1ERC20Gateway standardGateway = L1ERC20Gateway( - address( - new TransparentUpgradeableProxy( - address(standardGatewayTemplate), - proxyAdmin, - bytes("") - ) - ) - ); - L1CustomGateway customGateway = L1CustomGateway( - address( - new TransparentUpgradeableProxy( - address(customGatewayTemplate), - proxyAdmin, - bytes("") - ) - ) - ); - - emit OrbitTokenBridgeCreated(address(router), address(standardGateway), address(customGateway), proxyAdmin); - } - - function initTokenBridge( - L1GatewayRouter router, - L1ERC20Gateway standardGateway, - L1CustomGateway customGateway, - address owner, - address inbox, - address l2Router, - address l2StandardGateway, - address l2CustomGateway, - bytes32 cloneableProxyHash, - address l2BeaconProxyFactory - ) external { - /// dependencies - l2Router, l2StandardGateway, l2CustomGateway, cloneableProxyHash, l2BeaconProxyFactory, owner, inbox - router.initialize(owner, address(standardGateway), address(0), l2Router, inbox); - standardGateway.initialize(l2StandardGateway, address(router), inbox, cloneableProxyHash, l2BeaconProxyFactory); - customGateway.initialize(l2CustomGateway, address(router), inbox, owner); - } -} diff --git a/package.json b/package.json index 4848db18c2..434145c2c5 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "test:l2": "hardhat test test/*.l2.ts", "test:storage": "./scripts/storage_layout_test.bash", "deploy:tokenbridge:script": "ts-node ./scripts/local-deployment/tokenBridgeDeployer.ts", - "deploy:tokenbridge:factories": "ts-node ./scripts/local-deployment/factoryTokenBridgeDeployer.ts", "deploy:tokenbridge:atomic": "ts-node ./scripts/local-deployment/atomicTokenBridgeDeployer.ts", "test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.ts", "typechain": "hardhat typechain", From 1dac98a7cdc2e41a5a02c33b405ad4f0662c8a8d Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 11 Jul 2023 13:48:04 +0200 Subject: [PATCH 112/163] Use pre-set gas limit for deploying L2 factory --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 30 +++++--- .../atomicTokenBridgeDeployer.ts | 69 +++++++++++++------ 2 files changed, 68 insertions(+), 31 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index f00b40254f..96281240c3 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -45,6 +45,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // non-canonical router registry mapping(address => address) public inboxToNonCanonicalRouter; + // hard-code it to make sure gas limit is big enough for deployment to succeed + uint256 public gasLimitForL2FactoryDeployment; + // L1 logic contracts shared by all token bridges L1GatewayRouter public routerTemplate; L1ERC20Gateway public standardGatewayTemplate; @@ -102,7 +105,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address _l2CustomGatewayTemplate, address _l2WethGatewayTemplate, address _l2WethTemplate, - address _l1Weth + address _l1Weth, + uint256 _gasLimitForL2FactoryDeployment ) external onlyOwner { routerTemplate = _router; standardGatewayTemplate = _standardGateway; @@ -118,6 +122,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { l1Weth = _l1Weth; + gasLimitForL2FactoryDeployment = _gasLimitForL2FactoryDeployment; + emit OrbitTokenBridgeTemplatesUpdated(); } @@ -127,19 +133,18 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { * 2 retryable tickets to deploy L2 side. 1st one deploy L2 factory and 2nd calls function that deploys and inits * all the rest of the contracts. L2 chain is determined by `inbox` parameter. */ - function createTokenBridge(address inbox, uint256 maxGasForFactory, uint256 maxGasForContracts, uint256 gasPriceBid) - external - payable - { + function createTokenBridge(address inbox, uint256 maxGasForContracts, uint256 gasPriceBid) external payable { if (address(routerTemplate) == address(0)) { revert L1AtomicTokenBridgeCreator_TemplatesNotSet(); } + + // deploy L1 side of token bridge address owner = _getRollupOwner(inbox); (address router, address standardGateway, address customGateway, address wethGateway) = _deployL1Contracts(inbox, owner); /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls - uint256 valueSpentForFactory = _deployL2Factory(inbox, maxGasForFactory, gasPriceBid); + uint256 valueSpentForFactory = _deployL2Factory(inbox, gasPriceBid); uint256 valueSpentForContracts = _deployL2Contracts( router, standardGateway, customGateway, wethGateway, inbox, maxGasForContracts, gasPriceBid ); @@ -261,14 +266,21 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return address(wethGateway); } - function _deployL2Factory(address inbox, uint256 maxGas, uint256 gasPriceBid) internal returns (uint256) { + function _deployL2Factory(address inbox, uint256 gasPriceBid) internal returns (uint256) { // encode L2 factory bytecode bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); uint256 maxSubmissionCost = IInbox(inbox).calculateRetryableSubmissionFee(deploymentData.length, 0); - uint256 value = maxSubmissionCost + maxGas * gasPriceBid; + uint256 value = maxSubmissionCost + gasLimitForL2FactoryDeployment * gasPriceBid; IInbox(inbox).createRetryableTicket{value: value}( - address(0), 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, deploymentData + address(0), + 0, + maxSubmissionCost, + msg.sender, + msg.sender, + gasLimitForL2FactoryDeployment, + gasPriceBid, + deploymentData ); return value; diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 1a3bcfb83a..6b7591c91f 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -94,6 +94,7 @@ export const setupTokenBridgeInLocalEnv = async () => { ) const l1TokenBridgeCreator = await deployL1TokenBridgeCreator( l1Deployer, + l2Deployer, l1TokenBridgeCreatorOwner.address ) console.log('L1TokenBridgeCreator', l1TokenBridgeCreator.address) @@ -147,23 +148,17 @@ export const createTokenBridge = async ( l1TokenBridgeCreator: L1AtomicTokenBridgeCreator, inboxAddress: string ) => { - const deployerAddress = await l1Signer.getAddress() const gasPrice = await l2Signer.provider!.getGasPrice() //// run retryable estimate for deploying L2 factory - const l1ToL2MsgGasEstimate = new L1ToL2MessageGasEstimator(l2Signer.provider!) - const deployFactoryGasParams = await l1ToL2MsgGasEstimate.estimateAll( - { - from: l1TokenBridgeCreator.address, - to: ethers.constants.AddressZero, - l2CallValue: BigNumber.from(0), - excessFeeRefundAddress: deployerAddress, - callValueRefundAddress: deployerAddress, - data: L2AtomicTokenBridgeFactory__factory.bytecode, - }, - await getBaseFee(l1Signer.provider!), - l1Signer.provider! + const deployFactoryGasParams = await getEstimateForDeployingFactory( + l1Signer, + l2Signer, + l1TokenBridgeCreator.address ) + const maxGasForFactory = + await l1TokenBridgeCreator.gasLimitForL2FactoryDeployment() + const maxSubmissionCostForFactory = deployFactoryGasParams.maxSubmissionCost //// run retryable estimate for deploying L2 contracts //// we do this estimate using L2 factory template on L1 because on L2 factory does not yet exist @@ -189,22 +184,19 @@ export const createTokenBridge = async ( ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address ) - const maxGasForContracts = gasEstimateToDeployContracts.mul(2) + const maxGasForContracts = gasEstimateToDeployContracts const maxSubmissionCostForContracts = deployFactoryGasParams.maxSubmissionCost.mul(5) - let retryableValue = deployFactoryGasParams.maxSubmissionCost.add( - deployFactoryGasParams.gasLimit.mul(gasPrice) - ) - retryableValue = retryableValue.add( - maxSubmissionCostForContracts.add(maxGasForContracts.mul(gasPrice)) - ) + let retryableValue = maxSubmissionCostForFactory + .add(maxSubmissionCostForContracts) + .add(maxGasForFactory.mul(gasPrice)) + .add(maxGasForContracts.mul(gasPrice)) /// do it - create token bridge const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( inboxAddress, - deployFactoryGasParams.gasLimit, maxGasForContracts, gasPrice, { value: retryableValue } @@ -293,6 +285,7 @@ export const createTokenBridge = async ( const deployL1TokenBridgeCreator = async ( l1Signer: Signer, + l2Signer: Signer, l1CreatorOwner: string ) => { /// deploy creator behind proxy @@ -364,6 +357,13 @@ const deployL1TokenBridgeCreator = async ( const weth = ethers.Wallet.createRandom().address + //// run retryable estimate for deploying L2 factory + const deployFactoryGasParams = await getEstimateForDeployingFactory( + l1Signer, + l2Signer, + l1TokenBridgeCreator.address + ) + await ( await l1TokenBridgeCreator.setTemplates( routerTemplate.address, @@ -376,13 +376,38 @@ const deployL1TokenBridgeCreator = async ( l2CustomGatewayAddressOnL1.address, l2WethGatewayAddressOnL1.address, l2WethAddressOnL1.address, - weth + weth, + deployFactoryGasParams.gasLimit ) ).wait() return l1TokenBridgeCreator } +const getEstimateForDeployingFactory = async ( + l1Signer: Signer, + l2Signer: Signer, + deployer: string +) => { + //// run retryable estimate for deploying L2 factory + const deployerAddress = await l1Signer.getAddress() + const l1ToL2MsgGasEstimate = new L1ToL2MessageGasEstimator(l2Signer.provider!) + const deployFactoryGasParams = await l1ToL2MsgGasEstimate.estimateAll( + { + from: deployer, + to: ethers.constants.AddressZero, + l2CallValue: BigNumber.from(0), + excessFeeRefundAddress: deployerAddress, + callValueRefundAddress: deployerAddress, + data: L2AtomicTokenBridgeFactory__factory.bytecode, + }, + await getBaseFee(l1Signer.provider!), + l1Signer.provider! + ) + + return deployFactoryGasParams +} + export const getLocalNetworks = async ( l1Url: string, l2Url: string From 22545ce9522ac883ead9cb5be98eacd7f126bf08 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 11 Jul 2023 17:09:15 +0200 Subject: [PATCH 113/163] Separate L2 deployment to different contract --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 32 ++++++++++++------- .../ethereum/L1AtomicTokenBridgeCreator.sol | 30 +++++++++++++---- .../ethereum/L1TokenBridgeRetryableSender.sol | 30 +++++++++++++++++ 3 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index fbaf730d1f..f87ff61ee7 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -54,7 +54,7 @@ contract L2AtomicTokenBridgeFactory { // canonical L2 router with dummy logic address canonicalRouter = address( new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_ROUTER) }( - address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC)}()), + address(new CanonicalAddressSeed{ salt: _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC) }()), proxyAdmin, bytes("") ) @@ -79,7 +79,11 @@ contract L2AtomicTokenBridgeFactory { // canonical L2 standard gateway with dummy logic address canonicalStdGateway = address( new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY) }( - address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC)}()), + address( + new CanonicalAddressSeed{ + salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC) + }() + ), proxyAdmin, bytes("") ) @@ -114,7 +118,11 @@ contract L2AtomicTokenBridgeFactory { // canonical L2 custom gateway with dummy logic address canonicalCustomGateway = address( new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY) }( - address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC)}()), + address( + new CanonicalAddressSeed{ + salt: _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC) + }() + ), proxyAdmin, bytes("") ) @@ -140,10 +148,10 @@ contract L2AtomicTokenBridgeFactory { // canonical L2 WETH with dummy logic address canonicalL2Weth = address( new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH) }( - address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_WETH_LOGIC)}()), - proxyAdmin, - bytes("") - ) + address(new CanonicalAddressSeed{ salt: _getL2Salt(OrbitSalts.L2_WETH_LOGIC) }()), + proxyAdmin, + bytes("") + ) ); // create L2WETH logic and upgrade @@ -153,10 +161,12 @@ contract L2AtomicTokenBridgeFactory { // canonical L2 WETH gateway with dummy logic address canonicalL2WethGateway = address( new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY) }( - address(new CanonicalAddressSeed{salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC)}()), - proxyAdmin, - bytes("") - ) + address( + new CanonicalAddressSeed{ salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC) }() + ), + proxyAdmin, + bytes("") + ) ); // create L2WETH gateway logic and upgrade diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 96281240c3..6b034aadbc 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -1,17 +1,18 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.4; +import {L1TokenBridgeRetryableSender} from "./L1TokenBridgeRetryableSender.sol"; import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol"; import {L1ERC20Gateway} from "./gateway/L1ERC20Gateway.sol"; import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; import {L1WethGateway} from "./gateway/L1WethGateway.sol"; -import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { L2AtomicTokenBridgeFactory, CanonicalAddressSeed, OrbitSalts, - L2CreationCode + L2CreationCode, + ProxyAdmin } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; @@ -48,6 +49,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // hard-code it to make sure gas limit is big enough for deployment to succeed uint256 public gasLimitForL2FactoryDeployment; + // contract which creates retryables for deploying L2 side of token bridge + L1TokenBridgeRetryableSender public retryableSender; + // L1 logic contracts shared by all token bridges L1GatewayRouter public routerTemplate; L1ERC20Gateway public standardGatewayTemplate; @@ -78,6 +82,19 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { function initialize() public initializer { __Ownable_init(); + // deploy retryableSender only once - its address will be part of salt for L2 contracts + if (address(retryableSender) == address(0)) { + retryableSender = L1TokenBridgeRetryableSender( + address( + new TransparentUpgradeableProxy( + address(new L1TokenBridgeRetryableSender()), + msg.sender, + bytes("") + ) + ) + ); + } + canonicalL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); canonicalL2ProxyAdminAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), canonicalL2FactoryAddress @@ -295,7 +312,6 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { uint256 maxGas, uint256 gasPriceBid ) internal returns (uint256) { - address l2ProxyAdminOwner = _getRollupOwner(inbox); L2CreationCode memory l2Code = L2CreationCode( _creationCodeFor(l2RouterTemplate.code), _creationCodeFor(l2StandardGatewayTemplate.code), @@ -313,14 +329,14 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { l1WethGateway, l1Weth, getCanonicalL2StandardGatewayAddress(), - l2ProxyAdminOwner + _getRollupOwner(inbox) ) ); uint256 maxSubmissionCost = IInbox(inbox).calculateRetryableSubmissionFee(data.length, 0); uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - IInbox(inbox).createRetryableTicket{value: value}( - canonicalL2FactoryAddress, 0, maxSubmissionCost, msg.sender, msg.sender, maxGas, gasPriceBid, data + retryableSender.sendRetryable{value: value}( + inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxSubmissionCost, maxGas, gasPriceBid, data ); return value; @@ -490,6 +506,6 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { - return keccak256(abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(this)))); + return keccak256(abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(retryableSender)))); } } diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol new file mode 100644 index 0000000000..dde30b93a9 --- /dev/null +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.4; + +import {IInbox} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; + +/** + * @title Token Bridge Retryable Ticket Sender + * @notice This contract is intended to simply send out retryable ticket to deploy L2 side of the token bridge. + * Ticket data is prepared by L1AtomicTokenBridgeCreator. Retryable ticket issuance is done separately + * from L1 creator in order to have different senders for deployment of L2 factory vs. deployment of + * rest of L2 contracts. Having same sender can lead to edge cases where retryables are executed out + * order - that would prevent us from having canonical set of L2 addresses. + * + */ +contract L1TokenBridgeRetryableSender { + function sendRetryable( + address inbox, + address target, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 maxSubmissionCost, + uint256 maxGas, + uint256 gasPriceBid, + bytes calldata data + ) external payable { + IInbox(inbox).createRetryableTicket{value: msg.value}( + target, 0, maxSubmissionCost, excessFeeRefundAddress, callValueRefundAddress, maxGas, gasPriceBid, data + ); + } +} From dc4ca514ce1e0a24bc51e3c514ff39999432ffc2 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 11 Jul 2023 18:46:12 +0200 Subject: [PATCH 114/163] Do runtime to creation code conversion on L2 --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 47 ++++++++++---- .../ethereum/L1AtomicTokenBridgeCreator.sol | 64 +++++++++---------- .../atomicTokenBridgeDeployer.ts | 4 +- 3 files changed, 69 insertions(+), 46 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index f87ff61ee7..6d81b1d6f4 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -23,7 +23,7 @@ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; */ contract L2AtomicTokenBridgeFactory { function deployL2Contracts( - L2CreationCode calldata l2Code, + L2RuntimeCode calldata l2Code, address l1Router, address l1StandardGateway, address l1CustomGateway, @@ -46,7 +46,7 @@ contract L2AtomicTokenBridgeFactory { } function _deployRouter( - bytes calldata creationCode, + bytes calldata runtimeCode, address l1Router, address l2StandardGatewayCanonicalAddress, address proxyAdmin @@ -61,7 +61,7 @@ contract L2AtomicTokenBridgeFactory { ); // create L2 router logic and upgrade - address routerLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), creationCode); + address routerLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), _creationCodeFor(runtimeCode)); ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalRouter), routerLogic); // init @@ -71,7 +71,7 @@ contract L2AtomicTokenBridgeFactory { } function _deployStandardGateway( - bytes calldata creationCode, + bytes calldata runtimeCode, address l1StandardGateway, address router, address proxyAdmin @@ -90,7 +90,8 @@ contract L2AtomicTokenBridgeFactory { ); // create L2 standard gateway logic and upgrade - address stdGatewayLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), creationCode); + address stdGatewayLogic = + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), _creationCodeFor(runtimeCode)); ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalStdGateway), stdGatewayLogic); // create beacon @@ -110,7 +111,7 @@ contract L2AtomicTokenBridgeFactory { } function _deployCustomGateway( - bytes calldata creationCode, + bytes calldata runtimeCode, address l1CustomGateway, address router, address proxyAdmin @@ -130,7 +131,7 @@ contract L2AtomicTokenBridgeFactory { // create L2 custom gateway logic and upgrade address customGatewayLogicAddress = - Create2.deploy(0, _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), creationCode); + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), _creationCodeFor(runtimeCode)); ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalCustomGateway), customGatewayLogicAddress); // init @@ -138,8 +139,8 @@ contract L2AtomicTokenBridgeFactory { } function _deployWethGateway( - bytes calldata wethGatewayCreationCode, - bytes calldata aeWethCreationCode, + bytes calldata wethGatewayRuntimeCode, + bytes calldata aeWethRuntimeCode, address l1WethGateway, address l1Weth, address router, @@ -155,7 +156,8 @@ contract L2AtomicTokenBridgeFactory { ); // create L2WETH logic and upgrade - address l2WethLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_LOGIC), aeWethCreationCode); + address l2WethLogic = + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_LOGIC), _creationCodeFor(aeWethRuntimeCode)); ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalL2Weth), l2WethLogic); // canonical L2 WETH gateway with dummy logic @@ -171,7 +173,7 @@ contract L2AtomicTokenBridgeFactory { // create L2WETH gateway logic and upgrade address l2WethGatewayLogic = - Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), wethGatewayCreationCode); + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), _creationCodeFor(wethGatewayRuntimeCode)); ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalL2WethGateway), l2WethGatewayLogic); // init gateway @@ -186,6 +188,27 @@ contract L2AtomicTokenBridgeFactory { function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { return keccak256(abi.encodePacked(prefix, msg.sender)); } + + /** + * @notice Generate a creation code that results on a contract with `code` as bytecode. + * Source - https://github.com/0xsequence/sstore2/blob/master/contracts/utils/Bytecode.sol + * @param code The returning value of the resulting `creationCode` + * @return creationCode (constructor) for new contract + */ + function _creationCodeFor(bytes memory code) internal pure returns (bytes memory) { + /* + 0x00 0x63 0x63XXXXXX PUSH4 _code.length size + 0x01 0x80 0x80 DUP1 size size + 0x02 0x60 0x600e PUSH1 14 14 size size + 0x03 0x60 0x6000 PUSH1 00 0 14 size size + 0x04 0x39 0x39 CODECOPY size + 0x05 0x60 0x6000 PUSH1 00 0 size + 0x06 0xf3 0xf3 RETURN + + */ + + return abi.encodePacked(hex"63", uint32(code.length), hex"80600E6000396000F3", code); + } } /** @@ -196,7 +219,7 @@ contract CanonicalAddressSeed {} /** * Placeholder for bytecode of token bridge contracts which is sent from L1 to L2 through retryable ticket. */ -struct L2CreationCode { +struct L2RuntimeCode { bytes router; bytes standardGateway; bytes customGateway; diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 6b034aadbc..e540aae0ff 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -11,7 +11,7 @@ import { L2AtomicTokenBridgeFactory, CanonicalAddressSeed, OrbitSalts, - L2CreationCode, + L2RuntimeCode, ProxyAdmin } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; @@ -87,9 +87,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { retryableSender = L1TokenBridgeRetryableSender( address( new TransparentUpgradeableProxy( - address(new L1TokenBridgeRetryableSender()), - msg.sender, - bytes("") + address(new L1TokenBridgeRetryableSender()), + msg.sender, + bytes("") ) ) ); @@ -312,12 +312,12 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { uint256 maxGas, uint256 gasPriceBid ) internal returns (uint256) { - L2CreationCode memory l2Code = L2CreationCode( - _creationCodeFor(l2RouterTemplate.code), - _creationCodeFor(l2StandardGatewayTemplate.code), - _creationCodeFor(l2CustomGatewayTemplate.code), - _creationCodeFor(l2WethGatewayTemplate.code), - _creationCodeFor(l2WethTemplate.code) + L2RuntimeCode memory l2Code = L2RuntimeCode( + l2RouterTemplate.code, + l2StandardGatewayTemplate.code, + l2CustomGatewayTemplate.code, + l2WethGatewayTemplate.code, + l2WethTemplate.code ); bytes memory data = abi.encodeCall( L2AtomicTokenBridgeFactory.deployL2Contracts, @@ -454,6 +454,28 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); } + /** + * @notice Compute address of contract deployed using CREATE opcode + * @return computed address + */ + function _computeAddress(address origin, uint256 nonce) internal pure returns (address) { + bytes memory data; + if (nonce == 0x00) { + data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), origin, bytes1(0x80)); + } else if (nonce <= 0x7f) { + data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), origin, uint8(nonce)); + } else if (nonce <= 0xff) { + data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), origin, bytes1(0x81), uint8(nonce)); + } else if (nonce <= 0xffff) { + data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), origin, bytes1(0x82), uint16(nonce)); + } else if (nonce <= 0xffffff) { + data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), origin, bytes1(0x83), uint24(nonce)); + } else { + data = abi.encodePacked(bytes1(0xda), bytes1(0x94), origin, bytes1(0x84), uint32(nonce)); + } + return address(uint160(uint256(keccak256(data)))); + } + /** * @notice Generate a creation code that results on a contract with `code` as bytecode. * Source - https://github.com/0xsequence/sstore2/blob/master/contracts/utils/Bytecode.sol @@ -475,28 +497,6 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return abi.encodePacked(hex"63", uint32(code.length), hex"80600E6000396000F3", code); } - /** - * @notice Compute address of contract deployed using CREATE opcode - * @return computed address - */ - function _computeAddress(address _origin, uint256 _nonce) public pure returns (address) { - bytes memory data; - if (_nonce == 0x00) { - data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, bytes1(0x80)); - } else if (_nonce <= 0x7f) { - data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, uint8(_nonce)); - } else if (_nonce <= 0xff) { - data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), _origin, bytes1(0x81), uint8(_nonce)); - } else if (_nonce <= 0xffff) { - data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), _origin, bytes1(0x82), uint16(_nonce)); - } else if (_nonce <= 0xffffff) { - data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), _origin, bytes1(0x83), uint24(_nonce)); - } else { - data = abi.encodePacked(bytes1(0xda), bytes1(0x94), _origin, bytes1(0x84), uint32(_nonce)); - } - return address(uint160(uint256(keccak256(data)))); - } - function _getRollupOwner(address inbox) internal view returns (address) { return IInbox(inbox).bridge().rollup().owner(); } diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/local-deployment/atomicTokenBridgeDeployer.ts index 6b7591c91f..ca3489c1ca 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/local-deployment/atomicTokenBridgeDeployer.ts @@ -184,9 +184,9 @@ export const createTokenBridge = async ( ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address ) - const maxGasForContracts = gasEstimateToDeployContracts + const maxGasForContracts = gasEstimateToDeployContracts.mul(2) const maxSubmissionCostForContracts = - deployFactoryGasParams.maxSubmissionCost.mul(5) + deployFactoryGasParams.maxSubmissionCost.mul(2) let retryableValue = maxSubmissionCostForFactory .add(maxSubmissionCostForContracts) From 5e130e5521d4dba33e9f22ffebd467f6d699869b Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 12 Jul 2023 08:29:40 +0200 Subject: [PATCH 115/163] Add more code comments --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index e540aae0ff..64d46ca826 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -46,7 +46,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // non-canonical router registry mapping(address => address) public inboxToNonCanonicalRouter; - // hard-code it to make sure gas limit is big enough for deployment to succeed + // Hard-code gas to make sure gas limit is big enough for L2 factory deployment to succeed. + // If retryable would've reverted due to too low gas limit, nonce 0 would be burned and + // canonical address for L2 factory would've been unobtainable uint256 public gasLimitForL2FactoryDeployment; // contract which creates retryables for deploying L2 side of token bridge @@ -70,7 +72,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address public l1Weth; // immutable canonical addresses for L2 contracts - // other canonical addresses (dependent on L2 template implementations) can be fetched through `computeExpectedL2***Address` functions + // other canonical addresses (dependent on L2 template implementations) can be fetched through `getCanonicalL2***Address` functions address public canonicalL2FactoryAddress; address public canonicalL2ProxyAdminAddress; address public canonicalL2BeaconProxyFactoryAddress; @@ -147,8 +149,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { /** * @notice Deploy and initialize token bridge, both L1 and L2 sides, as part of a single TX. * @dev This is a single entrypoint of L1 token bridge creator. Function deploys L1 side of token bridge and then uses - * 2 retryable tickets to deploy L2 side. 1st one deploy L2 factory and 2nd calls function that deploys and inits - * all the rest of the contracts. L2 chain is determined by `inbox` parameter. + * 2 retryable tickets to deploy L2 side. 1st retryable deploys L2 factory. And then 'retryable sender' contract + * is called to issue 2nd retryable which deploys and inits the rest of the contracts. L2 chain is determined by `inbox` parameter. */ function createTokenBridge(address inbox, uint256 maxGasForContracts, uint256 gasPriceBid) external payable { if (address(routerTemplate) == address(0)) { From 66292b204c7c467776c835e87be0bfb1c410abde Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 12 Jul 2023 09:43:12 +0200 Subject: [PATCH 116/163] Add comment that only 1 token bridge can be deployed per inbox --- .../tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 64d46ca826..281b74315e 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -149,8 +149,13 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { /** * @notice Deploy and initialize token bridge, both L1 and L2 sides, as part of a single TX. * @dev This is a single entrypoint of L1 token bridge creator. Function deploys L1 side of token bridge and then uses - * 2 retryable tickets to deploy L2 side. 1st retryable deploys L2 factory. And then 'retryable sender' contract - * is called to issue 2nd retryable which deploys and inits the rest of the contracts. L2 chain is determined by `inbox` parameter. + * 2 retryable tickets to deploy L2 side. 1st retryable deploys L2 factory. And then 'retryable sender' contract + * is called to issue 2nd retryable which deploys and inits the rest of the contracts. L2 chain is determined + * by `inbox` parameter. + * + * Token bridge can be deployed only once for certain inbox. Any further calls to `createTokenBridge` will revert + * because L1 salts are already used at that point and L1 contracts are already deployed at canonical addresses + * for that inbox. */ function createTokenBridge(address inbox, uint256 maxGasForContracts, uint256 gasPriceBid) external payable { if (address(routerTemplate) == address(0)) { From 96fe4ca83ae1951e05142e39b7fb5afc12fa70a8 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Wed, 12 Jul 2023 12:32:15 +0200 Subject: [PATCH 117/163] Move logic for creating L2 side of token bridge to retryable sender contract. --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 63 +++++------ .../ethereum/L1TokenBridgeRetryableSender.sol | 103 ++++++++++++++++-- 2 files changed, 118 insertions(+), 48 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 281b74315e..adf319d7fc 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -1,7 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.4; -import {L1TokenBridgeRetryableSender} from "./L1TokenBridgeRetryableSender.sol"; +import { + L1TokenBridgeRetryableSender, + L1Addresses, + RetryableParams, + L2TemplateAddresses +} from "./L1TokenBridgeRetryableSender.sol"; import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol"; import {L1ERC20Gateway} from "./gateway/L1ERC20Gateway.sol"; import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; @@ -28,7 +33,6 @@ import {Initializable, OwnableUpgradeable} from "@openzeppelin/contracts-upgrade contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { error L1AtomicTokenBridgeCreator_OnlyRollupOwner(); error L1AtomicTokenBridgeCreator_InvalidRouterAddr(); - error L1AtomicTokenBridgeCreator_RefundFailed(); error L1AtomicTokenBridgeCreator_TemplatesNotSet(); event OrbitTokenBridgeCreated( @@ -169,14 +173,10 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls uint256 valueSpentForFactory = _deployL2Factory(inbox, gasPriceBid); - uint256 valueSpentForContracts = _deployL2Contracts( - router, standardGateway, customGateway, wethGateway, inbox, maxGasForContracts, gasPriceBid + uint256 fundsRemaining = msg.value - valueSpentForFactory; + _deployL2Contracts( + router, standardGateway, customGateway, wethGateway, inbox, maxGasForContracts, gasPriceBid, fundsRemaining ); - - // refund excess value to the sender - uint256 refund = msg.value - (valueSpentForFactory + valueSpentForContracts); - (bool success,) = msg.sender.call{value: refund}(""); - if (!success) revert L1AtomicTokenBridgeCreator_RefundFailed(); } /** @@ -317,36 +317,23 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address l1WethGateway, address inbox, uint256 maxGas, - uint256 gasPriceBid - ) internal returns (uint256) { - L2RuntimeCode memory l2Code = L2RuntimeCode( - l2RouterTemplate.code, - l2StandardGatewayTemplate.code, - l2CustomGatewayTemplate.code, - l2WethGatewayTemplate.code, - l2WethTemplate.code - ); - bytes memory data = abi.encodeCall( - L2AtomicTokenBridgeFactory.deployL2Contracts, - ( - l2Code, - l1Router, - l1StandardGateway, - l1CustomGateway, - l1WethGateway, - l1Weth, - getCanonicalL2StandardGatewayAddress(), - _getRollupOwner(inbox) - ) - ); - - uint256 maxSubmissionCost = IInbox(inbox).calculateRetryableSubmissionFee(data.length, 0); - uint256 value = maxSubmissionCost + maxGas * gasPriceBid; - retryableSender.sendRetryable{value: value}( - inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxSubmissionCost, maxGas, gasPriceBid, data + uint256 gasPriceBid, + uint256 availableFunds + ) internal { + retryableSender.sendRetryable{value: availableFunds}( + RetryableParams(inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxGas, gasPriceBid), + L2TemplateAddresses( + l2RouterTemplate, + l2StandardGatewayTemplate, + l2CustomGatewayTemplate, + l2WethGatewayTemplate, + l2WethTemplate + ), + L1Addresses(l1Router, l1StandardGateway, l1CustomGateway, l1WethGateway, l1Weth), + getCanonicalL2StandardGatewayAddress(), + _getRollupOwner(inbox), + msg.sender ); - - return value; } function getCanonicalL1RouterAddress(address inbox) public view returns (address) { diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index dde30b93a9..18dbd70396 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.4; import {IInbox} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; +import {L2AtomicTokenBridgeFactory, L2RuntimeCode} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; /** * @title Token Bridge Retryable Ticket Sender @@ -13,18 +14,100 @@ import {IInbox} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; * */ contract L1TokenBridgeRetryableSender { + error L1TokenBridgeRetryableSender_RefundFailed(); + + /** + * @notice Creates retryable which deploys L2 side of the token bridge. + * @dev Function will build retryable data, calculate submission cost and retryable value, create retryable + * and then refund the remaining funds to original delpoyer. + */ function sendRetryable( - address inbox, - address target, - address excessFeeRefundAddress, - address callValueRefundAddress, - uint256 maxSubmissionCost, - uint256 maxGas, - uint256 gasPriceBid, - bytes calldata data + RetryableParams calldata retryableParams, + L2TemplateAddresses calldata l2, + L1Addresses calldata l1, + address l2StandardGatewayAddress, + address rollupOwner, + address deployer ) external payable { - IInbox(inbox).createRetryableTicket{value: msg.value}( - target, 0, maxSubmissionCost, excessFeeRefundAddress, callValueRefundAddress, maxGas, gasPriceBid, data + bytes memory data = abi.encodeCall( + L2AtomicTokenBridgeFactory.deployL2Contracts, + ( + L2RuntimeCode( + l2.routerTemplate.code, + l2.standardGatewayTemplate.code, + l2.customGatewayTemplate.code, + l2.wethGatewayTemplate.code, + l2.wethTemplate.code + ), + l1.router, + l1.standardGateway, + l1.customGateway, + l1.wethGateway, + l1.weth, + l2StandardGatewayAddress, + rollupOwner + ) + ); + + uint256 maxSubmissionCost = IInbox(retryableParams.inbox).calculateRetryableSubmissionFee(data.length, 0); + uint256 retryableValue = maxSubmissionCost + retryableParams.maxGas * retryableParams.gasPriceBid; + _createRetryable(retryableParams, maxSubmissionCost, retryableValue, data); + + // refund excess value to the deployer + uint256 refund = msg.value - retryableValue; + (bool success,) = deployer.call{value: refund}(""); + if (!success) revert L1TokenBridgeRetryableSender_RefundFailed(); + } + + function _createRetryable( + RetryableParams calldata retryableParams, + uint256 maxSubmissionCost, + uint256 value, + bytes memory data + ) internal { + IInbox(retryableParams.inbox).createRetryableTicket{value: value}( + retryableParams.target, + 0, + maxSubmissionCost, + retryableParams.excessFeeRefundAddress, + retryableParams.callValueRefundAddress, + retryableParams.maxGas, + retryableParams.gasPriceBid, + data ); } } + +/** + * retryableParams needed to send retryable ticket + */ +struct RetryableParams { + address inbox; + address target; + address excessFeeRefundAddress; + address callValueRefundAddress; + uint256 maxGas; + uint256 gasPriceBid; +} + +/** + * Addresses of L2 templates deployed on L1 + */ +struct L2TemplateAddresses { + address routerTemplate; + address standardGatewayTemplate; + address customGatewayTemplate; + address wethGatewayTemplate; + address wethTemplate; +} + +/** + * L1 side of token bridge addresses + */ +struct L1Addresses { + address router; + address standardGateway; + address customGateway; + address wethGateway; + address weth; +} From 060c7d3ba142b54032d487836ca359db45586989 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 14 Jul 2023 15:20:39 +0200 Subject: [PATCH 118/163] Remove unused non-atomic deployers --- package.json | 3 +- .../tokenBridgeDeployerViaFactories.ts | 328 ------------------ 2 files changed, 1 insertion(+), 330 deletions(-) delete mode 100644 scripts/local-deployment/tokenBridgeDeployerViaFactories.ts diff --git a/package.json b/package.json index 434145c2c5..2954bc3635 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,7 @@ "test:l1": "hardhat test test/*.l1.ts", "test:l2": "hardhat test test/*.l2.ts", "test:storage": "./scripts/storage_layout_test.bash", - "deploy:tokenbridge:script": "ts-node ./scripts/local-deployment/tokenBridgeDeployer.ts", - "deploy:tokenbridge:atomic": "ts-node ./scripts/local-deployment/atomicTokenBridgeDeployer.ts", + "deploy:local:tokenbridge:atomic": "ts-node ./scripts/local-deployment/deploy.ts", "test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.ts", "typechain": "hardhat typechain", "deploy:tokenbridge": "hardhat run scripts/deploy_token_bridge_l1.ts --network mainnet", diff --git a/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts b/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts deleted file mode 100644 index 54bb87d0e7..0000000000 --- a/scripts/local-deployment/tokenBridgeDeployerViaFactories.ts +++ /dev/null @@ -1,328 +0,0 @@ -import { Contract, Signer, Wallet, ethers } from 'ethers' -import { - BeaconProxyFactory__factory, - L1CustomGateway__factory, - L1ERC20Gateway__factory, - L1GatewayRouter__factory, - L1TokenBridgeCreator__factory, - L2TokenBridgeFactory__factory, -} from '../../build/types' -import { JsonRpcProvider } from '@ethersproject/providers' -import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' -import { execSync } from 'child_process' -import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' -import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' -import * as fs from 'fs' - -export const setupTokenBridge = async ( - l1Deployer: Signer, - l2Deployer: Signer, - l1Url: string, - l2Url: string -) => { - const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( - l1Url, - l2Url - ) - - await bridgeFundsToL2Deployer(l1Deployer, coreL2Network.ethBridge.inbox) - - const deployedContracts = await deployTokenBridgeAndInit( - l1Deployer, - l2Deployer, - coreL2Network.ethBridge.inbox - ) - - const l2Network: L2Network = { - ...coreL2Network, - tokenBridge: { - l1CustomGateway: deployedContracts.l1CustomGateway, - l1ERC20Gateway: deployedContracts.l1StandardGateway, - l1GatewayRouter: deployedContracts.l1Router, - l1MultiCall: '', - l1ProxyAdmin: deployedContracts.l1ProxyAdmin, - l1Weth: '', - l1WethGateway: '', - - l2CustomGateway: deployedContracts.l2CustomGateway, - l2ERC20Gateway: deployedContracts.l2StandardGateway, - l2GatewayRouter: deployedContracts.l2Router, - l2Multicall: '', - l2ProxyAdmin: deployedContracts.l2ProxyAdmin, - l2Weth: '', - l2WethGateway: '', - }, - } - - addCustomNetwork({ - customL1Network: l1Network, - customL2Network: l2Network, - }) - - return { - l1Network, - l2Network, - } -} - -/** - * Deploy all the L1 and L2 contracts and do the initialization. - * - * @param l1Signer - * @param l2Signer - * @param inboxAddress - * @returns - */ -export const deployTokenBridgeAndInit = async ( - l1Signer: Signer, - l2Signer: Signer, - inboxAddress: string -) => { - // deploy L1 side - const l1TokenBridgeCreator = await deployTokenBridgeFactory(l1Signer) - - const receipt = await (await l1TokenBridgeCreator.createTokenBridge()).wait() - - const iface = l1TokenBridgeCreator.interface - const eventFragment = iface.getEvent('OrbitTokenBridgeCreated') - const parsedLog = receipt.logs - .filter( - (curr: any) => curr.topics[0] === iface.getEventTopic(eventFragment) - ) - .map((curr: any) => iface.parseLog(curr)) - const { - router: l1Router, - standardGateway: l1StandardGateway, - customGateway: l1CustomGateway, - proxyAdmin: l1ProxyAdmin, - } = parsedLog[0].args - - // deploy+init L2 side - const l2TokenBridgeFactory = await new L2TokenBridgeFactory__factory( - l2Signer - ).deploy(l1Router, l1StandardGateway, l1CustomGateway) - await l2TokenBridgeFactory.deployed() - const l2Receipt = await l2Signer.provider!.getTransactionReceipt( - l2TokenBridgeFactory.deployTransaction.hash - ) - - const l2Iface = l2TokenBridgeFactory.interface - const l2Event = l2Iface.getEvent('OrbitL2TokenBridgeCreated') - const parsedL2Log = l2Receipt.logs - .filter((curr: any) => curr.topics[0] === l2Iface.getEventTopic(l2Event)) - .map((curr: any) => l2Iface.parseLog(curr)) - const { - router: l2Router, - standardGateway: l2StandardGateway, - customGateway: l2CustomGateway, - beaconProxyFactory, - proxyAdmin: l2ProxyAdmin, - } = parsedL2Log[0].args - - // init L1 side - const cloneableProxyHash = await BeaconProxyFactory__factory.connect( - beaconProxyFactory, - l2Signer - ).cloneableProxyHash() - await ( - await l1TokenBridgeCreator.initTokenBridge( - l1Router, - l1StandardGateway, - l1CustomGateway, - await l1Signer.getAddress(), - inboxAddress, - l2Router, - l2StandardGateway, - l2CustomGateway, - cloneableProxyHash, - beaconProxyFactory - ) - ).wait() - - return { - l1Router, - l1StandardGateway, - l1CustomGateway, - l1ProxyAdmin, - l2Router, - l2StandardGateway, - l2CustomGateway, - beaconProxyFactory, - l2ProxyAdmin, - } -} - -const deployTokenBridgeFactory = async (l1Signer: Signer) => { - /// deploy factory - console.log('Deploy L1TokenBridgeCreator') - - const l1TokenBridgeCreator = await new L1TokenBridgeCreator__factory( - l1Signer - ).deploy() - await l1TokenBridgeCreator.deployed() - console.log('l1TokenBridgeCreator', l1TokenBridgeCreator.address) - - /// deploy logic contracts - console.log('Create and set logic contracts') - - const routerTemplate = await new L1GatewayRouter__factory(l1Signer).deploy() - await routerTemplate.deployed() - - const standardGatewayTemplate = await new L1ERC20Gateway__factory( - l1Signer - ).deploy() - await standardGatewayTemplate.deployed() - - const customGatewayTemplate = await new L1CustomGateway__factory( - l1Signer - ).deploy() - await customGatewayTemplate.deployed() - - await ( - await l1TokenBridgeCreator.setTemplates( - routerTemplate.address, - standardGatewayTemplate.address, - customGatewayTemplate.address - ) - ).wait() - - return l1TokenBridgeCreator -} - -const bridgeFundsToL2Deployer = async ( - l1Signer: Signer, - inboxAddress: string -) => { - console.log('fund L2 deployer') - - const depositAmount = ethers.utils.parseUnits('3', 'ether') - - // bridge it - const InboxAbi = ['function depositEth() public payable returns (uint256)'] - const Inbox = new Contract(inboxAddress, InboxAbi, l1Signer) - await (await Inbox.depositEth({ value: depositAmount })).wait() - await sleep(30 * 1000) -} - -export const getLocalNetworks = async ( - l1Url: string, - l2Url: string -): Promise<{ - l1Network: L1Network - l2Network: Omit -}> => { - const l1Provider = new JsonRpcProvider(l1Url) - const l2Provider = new JsonRpcProvider(l2Url) - let deploymentData: string - try { - deploymentData = execSync( - 'docker exec nitro_testnode_sequencer_1 cat /config/deployment.json' - ).toString() - } catch (e) { - deploymentData = execSync( - 'docker exec nitro-testnode-sequencer-1 cat /config/deployment.json' - ).toString() - } - const parsedDeploymentData = JSON.parse(deploymentData) as { - bridge: string - inbox: string - ['sequencer-inbox']: string - rollup: string - } - - const rollup = RollupAdminLogic__factory.connect( - parsedDeploymentData.rollup, - l1Provider - ) - const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() - - const bridge = Bridge__factory.connect( - parsedDeploymentData.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 = { - chainID: l2NetworkInfo.chainId, - confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), - ethBridge: { - bridge: parsedDeploymentData.bridge, - inbox: parsedDeploymentData.inbox, - outbox: outboxAddr, - rollup: parsedDeploymentData.rollup, - sequencerInbox: parsedDeploymentData['sequencer-inbox'], - }, - explorerUrl: '', - isArbitrum: true, - isCustom: true, - name: 'ArbLocal', - partnerChainID: l1NetworkInfo.chainId, - retryableLifetimeSeconds: 7 * 24 * 60 * 60, - nitroGenesisBlock: 0, - nitroGenesisL1Block: 0, - depositTimeout: 900000, - } - return { - l1Network, - l2Network, - } -} - -export const getSigner = (provider: JsonRpcProvider, key?: string) => { - if (!key && !provider) - throw new Error('Provide at least one of key or provider.') - if (key) return new Wallet(key).connect(provider) - else return provider.getSigner(0) -} - -export function sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)) -} - -async function main() { - const config = { - arbUrl: 'http://localhost:8547', - ethUrl: 'http://localhost:8545', - } - - const l1Provider = new ethers.providers.JsonRpcProvider(config.ethUrl) - const l2Provider = new ethers.providers.JsonRpcProvider(config.arbUrl) - - const l1DeployerWallet = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - l1Provider - ) - const l2DeployerWallet = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - l2Provider - ) - - const { l1Network, l2Network } = await setupTokenBridge( - l1DeployerWallet, - l2DeployerWallet, - config.ethUrl, - config.arbUrl - ) - - const NETWORK_FILE = 'network.json' - fs.writeFileSync( - NETWORK_FILE, - JSON.stringify({ l1Network, l2Network }, null, 2) - ) - console.log(NETWORK_FILE + ' updated') -} - -main().then(() => console.log('Done.')) From c99d9bbf14b82081c5db4f604ee5e4451b389c13 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 14 Jul 2023 15:25:51 +0200 Subject: [PATCH 119/163] Separate deployment of token bridge creator from chain specific setup --- .../atomicTokenBridgeDeployer.ts | 271 +++--------------- scripts/local-deployment/deploy.ts | 205 +++++++++++++ 2 files changed, 246 insertions(+), 230 deletions(-) rename scripts/{local-deployment => }/atomicTokenBridgeDeployer.ts (58%) create mode 100644 scripts/local-deployment/deploy.ts diff --git a/scripts/local-deployment/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts similarity index 58% rename from scripts/local-deployment/atomicTokenBridgeDeployer.ts rename to scripts/atomicTokenBridgeDeployer.ts index ca3489c1ca..7ef156daf1 100644 --- a/scripts/local-deployment/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -13,127 +13,18 @@ import { AeWETH__factory, L1WethGateway__factory, TransparentUpgradeableProxy__factory, -} from '../../build/types' + ProxyAdmin, + ProxyAdmin__factory, +} from '../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { - L1Network, L1ToL2MessageGasEstimator, L1ToL2MessageStatus, L1TransactionReceipt, - L2Network, - addCustomNetwork, } from '@arbitrum/sdk' -import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' -import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' -import * as fs from 'fs' import { exit } from 'process' -import { execSync } from 'child_process' import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' -/** - * Steps: - * - read network info from local container and register networks - * - deploy L1 bridge creator and set templates - * - do single TX deployment of token bridge - * - populate network objects with new addresses and return it - * - * @param l1Deployer - * @param l2Deployer - * @param l1Url - * @param l2Url - * @returns - */ -export const setupTokenBridgeInLocalEnv = async () => { - /// setup deployers, load local networks - const config = { - arbUrl: 'http://localhost:8547', - ethUrl: 'http://localhost:8545', - } - const l1Deployer = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - new ethers.providers.JsonRpcProvider(config.ethUrl) - ) - const l2Deployer = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - new ethers.providers.JsonRpcProvider(config.arbUrl) - ) - - const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( - config.ethUrl, - config.arbUrl - ) - - // register - needed for retryables - addCustomNetwork({ - customL1Network: l1Network, - customL2Network: { - ...coreL2Network, - tokenBridge: { - l1CustomGateway: '', - l1ERC20Gateway: '', - l1GatewayRouter: '', - l1MultiCall: '', - l1ProxyAdmin: '', - l1Weth: '', - l1WethGateway: '', - - l2CustomGateway: '', - l2ERC20Gateway: '', - l2GatewayRouter: '', - l2Multicall: '', - l2ProxyAdmin: '', - l2Weth: '', - l2WethGateway: '', - }, - }, - }) - - // prerequisite - deploy L1 creator and set templates - const l1TokenBridgeCreatorOwner = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user_b')) - ) - const l1TokenBridgeCreator = await deployL1TokenBridgeCreator( - l1Deployer, - l2Deployer, - l1TokenBridgeCreatorOwner.address - ) - console.log('L1TokenBridgeCreator', l1TokenBridgeCreator.address) - - // create token bridge - const deployedContracts = await createTokenBridge( - l1Deployer, - l2Deployer, - l1TokenBridgeCreator, - coreL2Network.ethBridge.inbox - ) - - const l2Network: L2Network = { - ...coreL2Network, - tokenBridge: { - l1CustomGateway: deployedContracts.l1CustomGateway, - l1ERC20Gateway: deployedContracts.l1StandardGateway, - l1GatewayRouter: deployedContracts.l1Router, - l1MultiCall: '', - l1ProxyAdmin: deployedContracts.l1ProxyAdmin, - l1Weth: deployedContracts.l1Weth, - l1WethGateway: deployedContracts.l1WethGateway, - - l2CustomGateway: deployedContracts.l2CustomGateway, - l2ERC20Gateway: deployedContracts.l2StandardGateway, - l2GatewayRouter: deployedContracts.l2Router, - l2Multicall: '', - l2ProxyAdmin: deployedContracts.l2ProxyAdmin, - l2Weth: deployedContracts.l2Weth, - l2WethGateway: deployedContracts.l2WethGateway, - }, - } - - return { - l1Network, - l2Network, - } -} - /** * Use already deployed L1TokenBridgeCreator to create and init token bridge contracts. * @@ -153,7 +44,7 @@ export const createTokenBridge = async ( //// run retryable estimate for deploying L2 factory const deployFactoryGasParams = await getEstimateForDeployingFactory( l1Signer, - l2Signer, + l2Signer.provider!, l1TokenBridgeCreator.address ) const maxGasForFactory = @@ -283,84 +174,96 @@ export const createTokenBridge = async ( } } -const deployL1TokenBridgeCreator = async ( - l1Signer: Signer, - l2Signer: Signer, - l1CreatorOwner: string +/** + * Deploy token bridge creator contract to base chain and set all the templates + * @param l1Deployer + * @param l2Provider + * @param l1WethAddress + * @returns + */ +export const deployL1TokenBridgeCreator = async ( + l1Deployer: Signer, + l2Provider: ethers.providers.Provider, + l1WethAddress: string ) => { /// deploy creator behind proxy + const l1TokenBridgeCreatorProxyAdmin = await new ProxyAdmin__factory( + l1Deployer + ).deploy() + await l1TokenBridgeCreatorProxyAdmin.deployed() + const l1TokenBridgeCreatorLogic = - await new L1AtomicTokenBridgeCreator__factory(l1Signer).deploy() + await new L1AtomicTokenBridgeCreator__factory(l1Deployer).deploy() await l1TokenBridgeCreatorLogic.deployed() const l1TokenBridgeCreatorProxy = - await new TransparentUpgradeableProxy__factory(l1Signer).deploy( + await new TransparentUpgradeableProxy__factory(l1Deployer).deploy( l1TokenBridgeCreatorLogic.address, - l1CreatorOwner, + l1TokenBridgeCreatorProxyAdmin.address, '0x' ) await l1TokenBridgeCreatorProxy.deployed() const l1TokenBridgeCreator = L1AtomicTokenBridgeCreator__factory.connect( l1TokenBridgeCreatorProxy.address, - l1Signer + l1Deployer ) await (await l1TokenBridgeCreator.initialize()).wait() /// deploy L1 logic contracts - const routerTemplate = await new L1GatewayRouter__factory(l1Signer).deploy() + const routerTemplate = await new L1GatewayRouter__factory(l1Deployer).deploy() await routerTemplate.deployed() const standardGatewayTemplate = await new L1ERC20Gateway__factory( - l1Signer + l1Deployer ).deploy() await standardGatewayTemplate.deployed() const customGatewayTemplate = await new L1CustomGateway__factory( - l1Signer + l1Deployer ).deploy() await customGatewayTemplate.deployed() const wethGatewayTemplate = await new L1WethGateway__factory( - l1Signer + l1Deployer ).deploy() await wethGatewayTemplate.deployed() /// deploy L2 contracts as placeholders on L1 const l2TokenBridgeFactoryOnL1 = - await new L2AtomicTokenBridgeFactory__factory(l1Signer).deploy() + await new L2AtomicTokenBridgeFactory__factory(l1Deployer).deploy() await l2TokenBridgeFactoryOnL1.deployed() const l2GatewayRouterOnL1 = await new L2GatewayRouter__factory( - l1Signer + l1Deployer ).deploy() await l2GatewayRouterOnL1.deployed() const l2StandardGatewayAddressOnL1 = await new L2ERC20Gateway__factory( - l1Signer + l1Deployer ).deploy() await l2StandardGatewayAddressOnL1.deployed() const l2CustomGatewayAddressOnL1 = await new L2CustomGateway__factory( - l1Signer + l1Deployer ).deploy() await l2CustomGatewayAddressOnL1.deployed() const l2WethGatewayAddressOnL1 = await new L2WethGateway__factory( - l1Signer + l1Deployer ).deploy() await l2WethGatewayAddressOnL1.deployed() - const l2WethAddressOnL1 = await new AeWETH__factory(l1Signer).deploy() + const l2WethAddressOnL1 = await new AeWETH__factory(l1Deployer).deploy() await l2WethAddressOnL1.deployed() const weth = ethers.Wallet.createRandom().address //// run retryable estimate for deploying L2 factory const deployFactoryGasParams = await getEstimateForDeployingFactory( - l1Signer, - l2Signer, + l1Deployer, + l2Provider, l1TokenBridgeCreator.address ) @@ -376,7 +279,7 @@ const deployL1TokenBridgeCreator = async ( l2CustomGatewayAddressOnL1.address, l2WethGatewayAddressOnL1.address, l2WethAddressOnL1.address, - weth, + l1WethAddress, deployFactoryGasParams.gasLimit ) ).wait() @@ -384,14 +287,14 @@ const deployL1TokenBridgeCreator = async ( return l1TokenBridgeCreator } -const getEstimateForDeployingFactory = async ( +export const getEstimateForDeployingFactory = async ( l1Signer: Signer, - l2Signer: Signer, + l2Provider: ethers.providers.Provider, deployer: string ) => { //// run retryable estimate for deploying L2 factory const deployerAddress = await l1Signer.getAddress() - const l1ToL2MsgGasEstimate = new L1ToL2MessageGasEstimator(l2Signer.provider!) + const l1ToL2MsgGasEstimate = new L1ToL2MessageGasEstimator(l2Provider) const deployFactoryGasParams = await l1ToL2MsgGasEstimate.estimateAll( { from: deployer, @@ -408,85 +311,6 @@ const getEstimateForDeployingFactory = async ( return deployFactoryGasParams } -export const getLocalNetworks = async ( - l1Url: string, - l2Url: string -): Promise<{ - l1Network: L1Network - l2Network: Omit -}> => { - const l1Provider = new JsonRpcProvider(l1Url) - const l2Provider = new JsonRpcProvider(l2Url) - let deploymentData: string - - let sequencerContainer = execSync( - 'docker ps --filter "name=sequencer" --format "{{.Names}}"' - ) - .toString() - .trim() - - deploymentData = execSync( - `docker exec ${sequencerContainer} cat /config/deployment.json` - ).toString() - - const parsedDeploymentData = JSON.parse(deploymentData) as { - bridge: string - inbox: string - ['sequencer-inbox']: string - rollup: string - } - - const rollup = RollupAdminLogic__factory.connect( - parsedDeploymentData.rollup, - l1Provider - ) - const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() - - const bridge = Bridge__factory.connect( - parsedDeploymentData.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 = { - chainID: l2NetworkInfo.chainId, - confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), - ethBridge: { - bridge: parsedDeploymentData.bridge, - inbox: parsedDeploymentData.inbox, - outbox: outboxAddr, - rollup: parsedDeploymentData.rollup, - sequencerInbox: parsedDeploymentData['sequencer-inbox'], - }, - explorerUrl: '', - isArbitrum: true, - isCustom: true, - name: 'ArbLocal', - partnerChainID: l1NetworkInfo.chainId, - retryableLifetimeSeconds: 7 * 24 * 60 * 60, - nitroGenesisBlock: 0, - nitroGenesisL1Block: 0, - depositTimeout: 900000, - } - return { - l1Network, - l2Network, - } -} - export const getSigner = (provider: JsonRpcProvider, key?: string) => { if (!key && !provider) throw new Error('Provide at least one of key or provider.') @@ -494,7 +318,7 @@ export const getSigner = (provider: JsonRpcProvider, key?: string) => { else return provider.getSigner(0) } -const getParsedLogs = ( +export const getParsedLogs = ( logs: ethers.providers.Log[], iface: ethers.utils.Interface, eventName: string @@ -511,16 +335,3 @@ const getParsedLogs = ( export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)) } - -async function main() { - const { l1Network, l2Network } = await setupTokenBridgeInLocalEnv() - - const NETWORK_FILE = 'network.json' - fs.writeFileSync( - NETWORK_FILE, - JSON.stringify({ l1Network, l2Network }, null, 2) - ) - console.log(NETWORK_FILE + ' updated') -} - -main().then(() => console.log('Done.')) diff --git a/scripts/local-deployment/deploy.ts b/scripts/local-deployment/deploy.ts new file mode 100644 index 0000000000..80c2d1c1d7 --- /dev/null +++ b/scripts/local-deployment/deploy.ts @@ -0,0 +1,205 @@ +import { ethers } from 'ethers' +import { JsonRpcProvider } from '@ethersproject/providers' +import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' +import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' +import * as fs from 'fs' +import { execSync } from 'child_process' +import { + createTokenBridge, + deployL1TokenBridgeCreator, +} from '../atomicTokenBridgeDeployer' + +/** + * Steps: + * - read network info from local container and register networks + * - deploy L1 bridge creator and set templates + * - do single TX deployment of token bridge + * - populate network objects with new addresses and return it + * + * @param l1Deployer + * @param l2Deployer + * @param l1Url + * @param l2Url + * @returns + */ +export const setupTokenBridgeInLocalEnv = async () => { + /// setup deployers, load local networks + const config = { + l1Url: 'http://localhost:8545', + l2Url: 'http://localhost:8547', + } + const l1Deployer = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + new ethers.providers.JsonRpcProvider(config.l1Url) + ) + const l2Deployer = new ethers.Wallet( + ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), + new ethers.providers.JsonRpcProvider(config.l2Url) + ) + + const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( + config.l1Url, + config.l2Url + ) + + // register - needed for retryables + addCustomNetwork({ + customL1Network: l1Network, + customL2Network: { + ...coreL2Network, + tokenBridge: { + l1CustomGateway: '', + l1ERC20Gateway: '', + l1GatewayRouter: '', + l1MultiCall: '', + l1ProxyAdmin: '', + l1Weth: '', + l1WethGateway: '', + + l2CustomGateway: '', + l2ERC20Gateway: '', + l2GatewayRouter: '', + l2Multicall: '', + l2ProxyAdmin: '', + l2Weth: '', + l2WethGateway: '', + }, + }, + }) + + // prerequisite - deploy L1 creator and set templates + const l1Weth = ethers.Wallet.createRandom().address + const l1TokenBridgeCreator = await deployL1TokenBridgeCreator( + l1Deployer, + l2Deployer.provider!, + l1Weth + ) + console.log('L1TokenBridgeCreator', l1TokenBridgeCreator.address) + + // create token bridge + const deployedContracts = await createTokenBridge( + l1Deployer, + l2Deployer, + l1TokenBridgeCreator, + coreL2Network.ethBridge.inbox + ) + + const l2Network: L2Network = { + ...coreL2Network, + tokenBridge: { + l1CustomGateway: deployedContracts.l1CustomGateway, + l1ERC20Gateway: deployedContracts.l1StandardGateway, + l1GatewayRouter: deployedContracts.l1Router, + l1MultiCall: '', + l1ProxyAdmin: deployedContracts.l1ProxyAdmin, + l1Weth: deployedContracts.l1Weth, + l1WethGateway: deployedContracts.l1WethGateway, + + l2CustomGateway: deployedContracts.l2CustomGateway, + l2ERC20Gateway: deployedContracts.l2StandardGateway, + l2GatewayRouter: deployedContracts.l2Router, + l2Multicall: '', + l2ProxyAdmin: deployedContracts.l2ProxyAdmin, + l2Weth: deployedContracts.l2Weth, + l2WethGateway: deployedContracts.l2WethGateway, + }, + } + + return { + l1Network, + l2Network, + } +} + +export const getLocalNetworks = async ( + l1Url: string, + l2Url: string +): Promise<{ + l1Network: L1Network + l2Network: Omit +}> => { + const l1Provider = new JsonRpcProvider(l1Url) + const l2Provider = new JsonRpcProvider(l2Url) + let deploymentData: string + + let sequencerContainer = execSync( + 'docker ps --filter "name=sequencer" --format "{{.Names}}"' + ) + .toString() + .trim() + + deploymentData = execSync( + `docker exec ${sequencerContainer} cat /config/deployment.json` + ).toString() + + const parsedDeploymentData = JSON.parse(deploymentData) as { + bridge: string + inbox: string + ['sequencer-inbox']: string + rollup: string + } + + const rollup = RollupAdminLogic__factory.connect( + parsedDeploymentData.rollup, + l1Provider + ) + const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() + + const bridge = Bridge__factory.connect( + parsedDeploymentData.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 = { + chainID: l2NetworkInfo.chainId, + confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), + ethBridge: { + bridge: parsedDeploymentData.bridge, + inbox: parsedDeploymentData.inbox, + outbox: outboxAddr, + rollup: parsedDeploymentData.rollup, + sequencerInbox: parsedDeploymentData['sequencer-inbox'], + }, + explorerUrl: '', + isArbitrum: true, + isCustom: true, + name: 'ArbLocal', + partnerChainID: l1NetworkInfo.chainId, + retryableLifetimeSeconds: 7 * 24 * 60 * 60, + nitroGenesisBlock: 0, + nitroGenesisL1Block: 0, + depositTimeout: 900000, + } + return { + l1Network, + l2Network, + } +} + +async function main() { + const { l1Network, l2Network } = await setupTokenBridgeInLocalEnv() + + const NETWORK_FILE = 'network.json' + fs.writeFileSync( + NETWORK_FILE, + JSON.stringify({ l1Network, l2Network }, null, 2) + ) + console.log(NETWORK_FILE + ' updated') +} + +main().then(() => console.log('Done.')) From 2f216796ccb198ae1f285ffc036b06312118e322 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 14 Jul 2023 16:53:37 +0200 Subject: [PATCH 120/163] Add script that deploys token bridge creator to ArbGoerli --- .env-sample | 4 + .github/workflows/build-test.yml | 2 +- .gitignore | 3 +- package.json | 3 +- scripts/atomicTokenBridgeDeployer.ts | 25 ++--- scripts/goerli-deployment/deploy.ts | 135 +++++++++++++++++++++++++++ 6 files changed, 154 insertions(+), 18 deletions(-) create mode 100644 .env-sample create mode 100644 scripts/goerli-deployment/deploy.ts diff --git a/.env-sample b/.env-sample new file mode 100644 index 0000000000..9e3413c0b9 --- /dev/null +++ b/.env-sample @@ -0,0 +1,4 @@ +## Goerli - Deploy L1TokenBridgeCreator +ARB_GOERLI_RPC="" +ARB_GOERLI_DEPLOYER_KEY="" +ORBIT_RPC="" \ No newline at end of file diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 14076ca8e9..ad682ff676 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -51,7 +51,7 @@ jobs: run: yarn build - name: Deploy token bridge - run: yarn run deploy:tokenbridge:atomic + run: yarn run deploy:local:token-bridge - name: Test token bridge deployment run: yarn run test:tokenbridge:deployment \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9058922686..6b2ee8afd5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.env node_modules #Hardhat files @@ -6,4 +7,4 @@ build artifacts deployment.json test/storage/*-old.dot -network.json \ No newline at end of file +network.json diff --git a/package.json b/package.json index 2954bc3635..4ac4170af9 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "test:l1": "hardhat test test/*.l1.ts", "test:l2": "hardhat test test/*.l2.ts", "test:storage": "./scripts/storage_layout_test.bash", - "deploy:local:tokenbridge:atomic": "ts-node ./scripts/local-deployment/deploy.ts", + "deploy:local:token-bridge": "ts-node ./scripts/local-deployment/deploy.ts", + "deploy:goerli:token-bridge-creator": "ts-node ./scripts/goerli-deployment/deploy.ts", "test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.ts", "typechain": "hardhat typechain", "deploy:tokenbridge": "hardhat run scripts/deploy_token_bridge_l1.ts --network mainnet", diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index 7ef156daf1..7aeb299ec3 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -44,8 +44,7 @@ export const createTokenBridge = async ( //// run retryable estimate for deploying L2 factory const deployFactoryGasParams = await getEstimateForDeployingFactory( l1Signer, - l2Signer.provider!, - l1TokenBridgeCreator.address + l2Signer.provider! ) const maxGasForFactory = await l1TokenBridgeCreator.gasLimitForL2FactoryDeployment() @@ -258,13 +257,10 @@ export const deployL1TokenBridgeCreator = async ( const l2WethAddressOnL1 = await new AeWETH__factory(l1Deployer).deploy() await l2WethAddressOnL1.deployed() - const weth = ethers.Wallet.createRandom().address - //// run retryable estimate for deploying L2 factory const deployFactoryGasParams = await getEstimateForDeployingFactory( l1Deployer, - l2Provider, - l1TokenBridgeCreator.address + l2Provider ) await ( @@ -288,24 +284,23 @@ export const deployL1TokenBridgeCreator = async ( } export const getEstimateForDeployingFactory = async ( - l1Signer: Signer, - l2Provider: ethers.providers.Provider, - deployer: string + l1Deployer: Signer, + l2Provider: ethers.providers.Provider ) => { //// run retryable estimate for deploying L2 factory - const deployerAddress = await l1Signer.getAddress() + const l1DeployerAddress = await l1Deployer.getAddress() const l1ToL2MsgGasEstimate = new L1ToL2MessageGasEstimator(l2Provider) const deployFactoryGasParams = await l1ToL2MsgGasEstimate.estimateAll( { - from: deployer, + from: ethers.Wallet.createRandom().address, to: ethers.constants.AddressZero, l2CallValue: BigNumber.from(0), - excessFeeRefundAddress: deployerAddress, - callValueRefundAddress: deployerAddress, + excessFeeRefundAddress: l1DeployerAddress, + callValueRefundAddress: l1DeployerAddress, data: L2AtomicTokenBridgeFactory__factory.bytecode, }, - await getBaseFee(l1Signer.provider!), - l1Signer.provider! + await getBaseFee(l1Deployer.provider!), + l1Deployer.provider! ) return deployFactoryGasParams diff --git a/scripts/goerli-deployment/deploy.ts b/scripts/goerli-deployment/deploy.ts new file mode 100644 index 0000000000..1c0498ba80 --- /dev/null +++ b/scripts/goerli-deployment/deploy.ts @@ -0,0 +1,135 @@ +import { JsonRpcProvider } from '@ethersproject/providers' +import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' +import { + deployL1TokenBridgeCreator, + getSigner, +} from '../atomicTokenBridgeDeployer' +import dotenv from 'dotenv' + +dotenv.config() + +export const envVars = { + baseChainRpc: process.env['ARB_GOERLI_RPC'] as string, + baseChainDeployerKey: process.env['ARB_GOERLI_DEPLOYER_KEY'] as string, + childChainRpc: process.env['ORBIT_RPC'] as string, +} + +const ARB_GOERLI_WETH = '0xEe01c0CD76354C383B8c7B4e65EA88D00B06f36f' + +/** + * Steps: + * - read network info from local container and register networks + * - deploy L1 bridge creator and set templates + * - do single TX deployment of token bridge + * - populate network objects with new addresses and return it + * + * @param l1Deployer + * @param l2Deployer + * @param l1Url + * @param l2Url + * @returns + */ +export const deployTokenBridgeCreator = async (rollupAddress: string) => { + if (envVars.baseChainRpc == undefined) + throw new Error('Missing ARB_GOERLI_RPC in env vars') + if (envVars.baseChainDeployerKey == undefined) + throw new Error('Missing ARB_GOERLI_DEPLOYER_KEY in env vars') + if (envVars.childChainRpc == undefined) + throw new Error('Missing ORBIT_RPC in env vars') + + const l1Provider = new JsonRpcProvider(envVars.baseChainRpc) + const l1Deployer = getSigner(l1Provider, envVars.baseChainDeployerKey) + const l2Provider = new JsonRpcProvider(envVars.childChainRpc) + + await registerGoerliNetworks(l1Provider, l2Provider, rollupAddress) + + // deploy L1 creator and set templates + const l1TokenBridgeCreator = await deployL1TokenBridgeCreator( + l1Deployer, + l2Provider, + ARB_GOERLI_WETH + ) + + return l1TokenBridgeCreator +} + +const registerGoerliNetworks = async ( + l1Provider: JsonRpcProvider, + l2Provider: JsonRpcProvider, + rollupAddress: 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 rollup = RollupAdminLogic__factory.connect(rollupAddress, l1Provider) + const l2Network: L2Network = { + 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, + } +} + +async function main() { + // this is just random Orbit rollup that will be used to estimate gas needed to deploy L2 token bridge factory via retryable + const rollupAddress = '0xDAB64b6E86035Aa9EB697341B663fb4B46930E60' + const l1TokenBridgeCreator = await deployTokenBridgeCreator(rollupAddress) + console.log('L1TokenBridgeCreator:', l1TokenBridgeCreator.address) +} + +main().then(() => console.log('Done.')) From 33fb2c140f36edcdaa49e674c944fca69717cc64 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 14 Jul 2023 17:43:51 +0200 Subject: [PATCH 121/163] Add script for creating token bridge for Orbit rollup --- package.json | 3 +- scripts/atomicTokenBridgeDeployer.ts | 20 +- .../goerli-deployment/createTokenBridge.ts | 178 ++++++++++++++++++ ...{deploy.ts => deployTokenBridgeCreator.ts} | 0 scripts/local-deployment/deploy.ts | 2 +- 5 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 scripts/goerli-deployment/createTokenBridge.ts rename scripts/goerli-deployment/{deploy.ts => deployTokenBridgeCreator.ts} (100%) diff --git a/package.json b/package.json index 4ac4170af9..75ff6ba7f4 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "test:l2": "hardhat test test/*.l2.ts", "test:storage": "./scripts/storage_layout_test.bash", "deploy:local:token-bridge": "ts-node ./scripts/local-deployment/deploy.ts", - "deploy:goerli:token-bridge-creator": "ts-node ./scripts/goerli-deployment/deploy.ts", + "deploy:goerli:token-bridge-creator": "ts-node ./scripts/goerli-deployment/deployTokenBridgeCreator.ts", + "create:goerli:token-bridge": "ts-node ./scripts/goerli-deployment/createTokenBridge.ts", "test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.ts", "typechain": "hardhat typechain", "deploy:tokenbridge": "hardhat run scripts/deploy_token_bridge_l1.ts --network mainnet", diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index 7aeb299ec3..b03ef2149c 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -35,21 +35,27 @@ import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' */ export const createTokenBridge = async ( l1Signer: Signer, - l2Signer: Signer, + l2Provider: ethers.providers.Provider, l1TokenBridgeCreator: L1AtomicTokenBridgeCreator, inboxAddress: string ) => { - const gasPrice = await l2Signer.provider!.getGasPrice() + const gasPrice = await l2Provider.getGasPrice() //// run retryable estimate for deploying L2 factory const deployFactoryGasParams = await getEstimateForDeployingFactory( l1Signer, - l2Signer.provider! + l2Provider ) const maxGasForFactory = await l1TokenBridgeCreator.gasLimitForL2FactoryDeployment() const maxSubmissionCostForFactory = deployFactoryGasParams.maxSubmissionCost + console.log( + 'deployFactoryGasParams', + maxGasForFactory.toString(), + maxSubmissionCostForFactory.toString() + ) + //// run retryable estimate for deploying L2 contracts //// we do this estimate using L2 factory template on L1 because on L2 factory does not yet exist const l2FactoryTemplate = L2AtomicTokenBridgeFactory__factory.connect( @@ -95,7 +101,7 @@ export const createTokenBridge = async ( /// wait for execution of both tickets const l1TxReceipt = new L1TransactionReceipt(receipt) - const messages = await l1TxReceipt.getL1ToL2Messages(l2Signer) + const messages = await l1TxReceipt.getL1ToL2Messages(l2Provider) const messageResults = await Promise.all( messages.map(message => message.waitForStatus()) ) @@ -122,7 +128,7 @@ export const createTokenBridge = async ( const l2AtomicTokenBridgeFactory = L2AtomicTokenBridgeFactory__factory.connect( messageResults[0].l2TxReceipt.contractAddress, - l2Signer + l2Provider ) console.log('L2AtomicTokenBridgeFactory', l2AtomicTokenBridgeFactory.address) @@ -143,14 +149,14 @@ export const createTokenBridge = async ( const l2Router = await l1TokenBridgeCreator.getCanonicalL2RouterAddress() const l2StandardGateway = L2ERC20Gateway__factory.connect( await l1TokenBridgeCreator.getCanonicalL2StandardGatewayAddress(), - l2Signer + l2Provider ) const beaconProxyFactory = await l2StandardGateway.beaconProxyFactory() const l2CustomGateway = await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress() const l2WethGateway = L2WethGateway__factory.connect( await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(), - l2Signer + l2Provider ) const l1Weth = await l1TokenBridgeCreator.l1Weth() const l2Weth = await l1TokenBridgeCreator.getCanonicalL2WethAddress() diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts new file mode 100644 index 0000000000..03700113c1 --- /dev/null +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -0,0 +1,178 @@ +import { JsonRpcProvider } from '@ethersproject/providers' +import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' +import { createTokenBridge, getSigner } from '../atomicTokenBridgeDeployer' +import dotenv from 'dotenv' +import { L1AtomicTokenBridgeCreator__factory } from '../../build/types' +import * as fs from 'fs' + +dotenv.config() + +export const envVars = { + baseChainRpc: process.env['ARB_GOERLI_RPC'] as string, + baseChainDeployerKey: process.env['ARB_GOERLI_DEPLOYER_KEY'] as string, + childChainRpc: process.env['ORBIT_RPC'] as string, +} + +const L1_TOKEN_BRIDGE_CREATOR = '0x0034ac7efa37293160EFbD35F671C77Ec22Dea0A' + +/** + * Steps: + * - read network info from local container and register networks + * - deploy L1 bridge creator and set templates + * - do single TX deployment of token bridge + * - populate network objects with new addresses and return it + * + * @param l1Deployer + * @param l2Deployer + * @param l1Url + * @param l2Url + * @returns + */ +export const _createTokenBridge = async (rollupAddress: string) => { + if (envVars.baseChainRpc == undefined) + throw new Error('Missing ARB_GOERLI_RPC in env vars') + if (envVars.baseChainDeployerKey == undefined) + throw new Error('Missing ARB_GOERLI_DEPLOYER_KEY in env vars') + if (envVars.childChainRpc == undefined) + throw new Error('Missing ORBIT_RPC in env vars') + + const l1Provider = new JsonRpcProvider(envVars.baseChainRpc) + const l1Deployer = getSigner(l1Provider, envVars.baseChainDeployerKey) + const l2Provider = new JsonRpcProvider(envVars.childChainRpc) + + console.log('registerGoerliNetworks') + const { l1Network, l2Network: corel2Network } = await registerGoerliNetworks( + l1Provider, + l2Provider, + rollupAddress + ) + + // create token bridge + const l1TokenBridgeCreator = L1AtomicTokenBridgeCreator__factory.connect( + L1_TOKEN_BRIDGE_CREATOR, + l1Deployer + ) + const inbox = await RollupAdminLogic__factory.connect( + rollupAddress, + l1Provider + ).inbox() + + const deployedContracts = await createTokenBridge( + l1Deployer, + l2Provider, + l1TokenBridgeCreator, + inbox + ) + + const l2Network = { + ...corel2Network, + tokenBridge: { + l1CustomGateway: deployedContracts.l1CustomGateway, + l1ERC20Gateway: deployedContracts.l1StandardGateway, + l1GatewayRouter: deployedContracts.l1Router, + l1MultiCall: '', + l1ProxyAdmin: deployedContracts.l1ProxyAdmin, + l1Weth: deployedContracts.l1Weth, + l1WethGateway: deployedContracts.l1WethGateway, + + l2CustomGateway: deployedContracts.l2CustomGateway, + l2ERC20Gateway: deployedContracts.l2StandardGateway, + l2GatewayRouter: deployedContracts.l2Router, + l2Multicall: '', + l2ProxyAdmin: deployedContracts.l2ProxyAdmin, + l2Weth: deployedContracts.l2Weth, + l2WethGateway: deployedContracts.l2WethGateway, + }, + } + + return { + l1Network, + l2Network, + } +} + +const registerGoerliNetworks = async ( + l1Provider: JsonRpcProvider, + l2Provider: JsonRpcProvider, + rollupAddress: 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 rollup = RollupAdminLogic__factory.connect(rollupAddress, l1Provider) + const l2Network: L2Network = { + 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, + } +} + +async function main() { + const rollupAddress = '0xDAB64b6E86035Aa9EB697341B663fb4B46930E60' + + const { l1Network, l2Network } = await _createTokenBridge(rollupAddress) + const NETWORK_FILE = 'network.json' + fs.writeFileSync( + NETWORK_FILE, + JSON.stringify({ l1Network, l2Network }, null, 2) + ) + console.log(NETWORK_FILE + ' updated') +} + +main().then(() => console.log('Done.')) diff --git a/scripts/goerli-deployment/deploy.ts b/scripts/goerli-deployment/deployTokenBridgeCreator.ts similarity index 100% rename from scripts/goerli-deployment/deploy.ts rename to scripts/goerli-deployment/deployTokenBridgeCreator.ts diff --git a/scripts/local-deployment/deploy.ts b/scripts/local-deployment/deploy.ts index 80c2d1c1d7..c556e84d3e 100644 --- a/scripts/local-deployment/deploy.ts +++ b/scripts/local-deployment/deploy.ts @@ -80,7 +80,7 @@ export const setupTokenBridgeInLocalEnv = async () => { // create token bridge const deployedContracts = await createTokenBridge( l1Deployer, - l2Deployer, + l2Deployer.provider!, l1TokenBridgeCreator, coreL2Network.ethBridge.inbox ) From 8bb7316e797e9d95eadcb28fd4c091df7582611e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 17 Jul 2023 11:29:04 +0200 Subject: [PATCH 122/163] Polish up script for creating new token bridge on Goerli --- scripts/atomicTokenBridgeDeployer.ts | 26 +++++++++++-------- .../goerli-deployment/createTokenBridge.ts | 24 ++++++++++------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index b03ef2149c..d3d39f8732 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -13,7 +13,6 @@ import { AeWETH__factory, L1WethGateway__factory, TransparentUpgradeableProxy__factory, - ProxyAdmin, ProxyAdmin__factory, } from '../build/types' import { JsonRpcProvider } from '@ethersproject/providers' @@ -24,20 +23,25 @@ import { } from '@arbitrum/sdk' import { exit } from 'process' import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' +import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' /** * Use already deployed L1TokenBridgeCreator to create and init token bridge contracts. + * Function first gets estimates for 2 retryable tickets - one for deploying L2 factory and + * one for deploying L2 side of token bridge. Then it creates retryables, waits for + * until they're executed, and finally it picks up addresses of new contracts. * * @param l1Signer - * @param l2Signer - * @param inboxAddress + * @param l2Provider + * @param l1TokenBridgeCreator + * @param rollupAddress * @returns */ export const createTokenBridge = async ( l1Signer: Signer, l2Provider: ethers.providers.Provider, l1TokenBridgeCreator: L1AtomicTokenBridgeCreator, - inboxAddress: string + rollupAddress: string ) => { const gasPrice = await l2Provider.getGasPrice() @@ -50,12 +54,6 @@ export const createTokenBridge = async ( await l1TokenBridgeCreator.gasLimitForL2FactoryDeployment() const maxSubmissionCostForFactory = deployFactoryGasParams.maxSubmissionCost - console.log( - 'deployFactoryGasParams', - maxGasForFactory.toString(), - maxSubmissionCostForFactory.toString() - ) - //// run retryable estimate for deploying L2 contracts //// we do this estimate using L2 factory template on L1 because on L2 factory does not yet exist const l2FactoryTemplate = L2AtomicTokenBridgeFactory__factory.connect( @@ -89,10 +87,16 @@ export const createTokenBridge = async ( .add(maxGasForFactory.mul(gasPrice)) .add(maxGasForContracts.mul(gasPrice)) + // get inbox from rollup contract + const inbox = await RollupAdminLogic__factory.connect( + rollupAddress, + l1Signer.provider! + ).inbox() + /// do it - create token bridge const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( - inboxAddress, + inbox, maxGasForContracts, gasPrice, { value: retryableValue } diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts index 03700113c1..40bf8d1516 100644 --- a/scripts/goerli-deployment/createTokenBridge.ts +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -29,7 +29,7 @@ const L1_TOKEN_BRIDGE_CREATOR = '0x0034ac7efa37293160EFbD35F671C77Ec22Dea0A' * @param l2Url * @returns */ -export const _createTokenBridge = async (rollupAddress: string) => { +export const createTokenBridgeOnGoerli = async (rollupAddress: string) => { if (envVars.baseChainRpc == undefined) throw new Error('Missing ARB_GOERLI_RPC in env vars') if (envVars.baseChainDeployerKey == undefined) @@ -41,7 +41,6 @@ export const _createTokenBridge = async (rollupAddress: string) => { const l1Deployer = getSigner(l1Provider, envVars.baseChainDeployerKey) const l2Provider = new JsonRpcProvider(envVars.childChainRpc) - console.log('registerGoerliNetworks') const { l1Network, l2Network: corel2Network } = await registerGoerliNetworks( l1Provider, l2Provider, @@ -53,16 +52,12 @@ export const _createTokenBridge = async (rollupAddress: string) => { L1_TOKEN_BRIDGE_CREATOR, l1Deployer ) - const inbox = await RollupAdminLogic__factory.connect( - rollupAddress, - l1Provider - ).inbox() const deployedContracts = await createTokenBridge( l1Deployer, l2Provider, l1TokenBridgeCreator, - inbox + rollupAddress ) const l2Network = { @@ -164,9 +159,20 @@ const registerGoerliNetworks = async ( } async function main() { - const rollupAddress = '0xDAB64b6E86035Aa9EB697341B663fb4B46930E60' + const args = process.argv.slice(2) + if (args.length != 1) { + console.log( + "Please provide exactly 1 argument - rollup address.\nIe. `yarn run create:goerli:token-bridge -- '0xDAB64b6E86035Aa9EB697341B663fb4B46930E60'`" + ) + return + } + + const rollupAddress = args[0] + console.log('Creating token bridge for rollup', rollupAddress) - const { l1Network, l2Network } = await _createTokenBridge(rollupAddress) + const { l1Network, l2Network } = await createTokenBridgeOnGoerli( + rollupAddress + ) const NETWORK_FILE = 'network.json' fs.writeFileSync( NETWORK_FILE, From c00bdbda923d1a1608a7e666d268eb56f9119fb3 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 17 Jul 2023 15:54:01 +0200 Subject: [PATCH 123/163] Only L1 creator can call sendRetryable of L1TokenBridgeRetryableSender --- .../tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol | 1 + .../ethereum/L1TokenBridgeRetryableSender.sol | 9 +++++++-- scripts/local-deployment/deploy.ts | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index adf319d7fc..7e5f0ee69b 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -99,6 +99,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ) ) ); + retryableSender.initialize(); } canonicalL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index 18dbd70396..cbdc010e2c 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.4; import {IInbox} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {L2AtomicTokenBridgeFactory, L2RuntimeCode} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; +import {Initializable, OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; /** * @title Token Bridge Retryable Ticket Sender @@ -13,9 +14,13 @@ import {L2AtomicTokenBridgeFactory, L2RuntimeCode} from "../arbitrum/L2AtomicTok * order - that would prevent us from having canonical set of L2 addresses. * */ -contract L1TokenBridgeRetryableSender { +contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { error L1TokenBridgeRetryableSender_RefundFailed(); + function initialize() public initializer { + __Ownable_init(); + } + /** * @notice Creates retryable which deploys L2 side of the token bridge. * @dev Function will build retryable data, calculate submission cost and retryable value, create retryable @@ -28,7 +33,7 @@ contract L1TokenBridgeRetryableSender { address l2StandardGatewayAddress, address rollupOwner, address deployer - ) external payable { + ) external payable onlyOwner { bytes memory data = abi.encodeCall( L2AtomicTokenBridgeFactory.deployL2Contracts, ( diff --git a/scripts/local-deployment/deploy.ts b/scripts/local-deployment/deploy.ts index c556e84d3e..803fe30a9b 100644 --- a/scripts/local-deployment/deploy.ts +++ b/scripts/local-deployment/deploy.ts @@ -82,7 +82,7 @@ export const setupTokenBridgeInLocalEnv = async () => { l1Deployer, l2Deployer.provider!, l1TokenBridgeCreator, - coreL2Network.ethBridge.inbox + coreL2Network.ethBridge.rollup ) const l2Network: L2Network = { From 33cc402d2f000ca1db2d36f0e8da8cfca927ac0b Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 17 Jul 2023 16:26:10 +0200 Subject: [PATCH 124/163] Update L1Creator Goerli address --- scripts/goerli-deployment/createTokenBridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts index 40bf8d1516..c5aca52f95 100644 --- a/scripts/goerli-deployment/createTokenBridge.ts +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -14,7 +14,7 @@ export const envVars = { childChainRpc: process.env['ORBIT_RPC'] as string, } -const L1_TOKEN_BRIDGE_CREATOR = '0x0034ac7efa37293160EFbD35F671C77Ec22Dea0A' +const L1_TOKEN_BRIDGE_CREATOR = '0xAd146718D61dc3024428ED7Ed11ade741A37EA38' /** * Steps: From d0dba7596e0cb168d7a3209fc698aa873467d480 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 18 Jul 2023 10:42:12 +0200 Subject: [PATCH 125/163] Support testing both local and goerli deployment --- test-e2e/tokenBridgeDeploymentTest.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index a734f246fc..bc10e4f482 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -34,8 +34,8 @@ import { expect } from 'chai' import { ethers } from 'hardhat' const config = { - arbUrl: 'http://localhost:8547', - ethUrl: 'http://localhost:8545', + l2Url: process.env.ORBIT_RPC || 'http://localhost:8547', + l1Url: process.env.ARB_GOERLI_RPC || 'http://localhost:8545', } let _l1Network: L1Network @@ -48,8 +48,8 @@ describe('tokenBridge', () => { it('should have deployed and initialized token bridge contracts', async function () { const { l1Network, l1Provider, l2Network, l2Provider } = await getProvidersAndSetupNetworks({ - l1Url: config.ethUrl, - l2Url: config.arbUrl, + l1Url: config.l1Url, + l2Url: config.l2Url, networkFilename: './network.json', }) From 902206edf01f4575d8be87415f632573bbac6354 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 27 Jul 2023 11:20:31 +0200 Subject: [PATCH 126/163] Set correct templates if fee token is used --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 190 ++++++++++++------ .../ethereum/L1TokenBridgeRetryableSender.sol | 48 ++++- foundry.toml | 2 +- lib/nitro-contracts | 2 +- 4 files changed, 169 insertions(+), 73 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 7e5f0ee69b..0693a7c859 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -11,7 +11,12 @@ import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol"; import {L1ERC20Gateway} from "./gateway/L1ERC20Gateway.sol"; import {L1CustomGateway} from "./gateway/L1CustomGateway.sol"; import {L1WethGateway} from "./gateway/L1WethGateway.sol"; -import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {L1OrbitGatewayRouter} from "./gateway/L1OrbitGatewayRouter.sol"; +import {L1OrbitERC20Gateway} from "./gateway/L1OrbitERC20Gateway.sol"; +import {L1OrbitCustomGateway} from "./gateway/L1OrbitCustomGateway.sol"; + +import {TransparentUpgradeableProxy} from + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { L2AtomicTokenBridgeFactory, CanonicalAddressSeed, @@ -19,11 +24,15 @@ import { L2RuntimeCode, ProxyAdmin } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; +import {BytesLib} from "../libraries/BytesLib.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; import {BeaconProxyFactory, ClonableBeaconProxy} from "../libraries/ClonableBeaconProxy.sol"; -import {Initializable, OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { + Initializable, + OwnableUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; /** * @title Layer1 token bridge creator @@ -47,6 +56,16 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { event OrbitTokenBridgeTemplatesUpdated(); event NonCanonicalRouterSet(address indexed inbox, address indexed router); + struct L1Templates { + L1GatewayRouter routerTemplate; + L1ERC20Gateway standardGatewayTemplate; + L1CustomGateway customGatewayTemplate; + L1WethGateway wethGatewayTemplate; + L1OrbitGatewayRouter orbitRouterTemplate; + L1OrbitERC20Gateway orbitStandardGatewayTemplate; + L1OrbitCustomGateway orbitCustomGatewayTemplate; + } + // non-canonical router registry mapping(address => address) public inboxToNonCanonicalRouter; @@ -59,10 +78,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { L1TokenBridgeRetryableSender public retryableSender; // L1 logic contracts shared by all token bridges - L1GatewayRouter public routerTemplate; - L1ERC20Gateway public standardGatewayTemplate; - L1CustomGateway public customGatewayTemplate; - L1WethGateway public wethGatewayTemplate; + L1Templates public l1Templates; // L2 contracts deployed to L1 as bytecode placeholders address public l2TokenBridgeFactoryTemplate; @@ -85,26 +101,18 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { _disableInitializers(); } - function initialize() public initializer { + function initialize(L1TokenBridgeRetryableSender _retryableSender) public initializer { __Ownable_init(); // deploy retryableSender only once - its address will be part of salt for L2 contracts - if (address(retryableSender) == address(0)) { - retryableSender = L1TokenBridgeRetryableSender( - address( - new TransparentUpgradeableProxy( - address(new L1TokenBridgeRetryableSender()), - msg.sender, - bytes("") - ) - ) - ); - retryableSender.initialize(); - } + retryableSender = _retryableSender; - canonicalL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); + canonicalL2FactoryAddress = + _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); canonicalL2ProxyAdminAddress = Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), canonicalL2FactoryAddress + _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), + keccak256(type(ProxyAdmin).creationCode), + canonicalL2FactoryAddress ); canonicalL2BeaconProxyFactoryAddress = Create2.computeAddress( _getL2Salt(OrbitSalts.BEACON_PROXY_FACTORY), @@ -119,10 +127,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { * payload used to deploy contracts on L2 side. */ function setTemplates( - L1GatewayRouter _router, - L1ERC20Gateway _standardGateway, - L1CustomGateway _customGateway, - L1WethGateway _wethGatewayTemplate, + L1Templates calldata _l1Templates, address _l2TokenBridgeFactoryTemplate, address _l2RouterTemplate, address _l2StandardGatewayTemplate, @@ -132,10 +137,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address _l1Weth, uint256 _gasLimitForL2FactoryDeployment ) external onlyOwner { - routerTemplate = _router; - standardGatewayTemplate = _standardGateway; - customGatewayTemplate = _customGateway; - wethGatewayTemplate = _wethGatewayTemplate; + l1Templates = _l1Templates; l2TokenBridgeFactoryTemplate = _l2TokenBridgeFactoryTemplate; l2RouterTemplate = _l2RouterTemplate; @@ -162,21 +164,33 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { * because L1 salts are already used at that point and L1 contracts are already deployed at canonical addresses * for that inbox. */ - function createTokenBridge(address inbox, uint256 maxGasForContracts, uint256 gasPriceBid) external payable { - if (address(routerTemplate) == address(0)) { + function createTokenBridge(address inbox, uint256 maxGasForContracts, uint256 gasPriceBid) + external + payable + { + if (address(l1Templates.routerTemplate) == address(0)) { revert L1AtomicTokenBridgeCreator_TemplatesNotSet(); } + bool isUsingFeeToken = _getFeeToken(inbox) != address(0); + // deploy L1 side of token bridge address owner = _getRollupOwner(inbox); (address router, address standardGateway, address customGateway, address wethGateway) = - _deployL1Contracts(inbox, owner); + _deployL1Contracts(inbox, owner, isUsingFeeToken); /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls uint256 valueSpentForFactory = _deployL2Factory(inbox, gasPriceBid); uint256 fundsRemaining = msg.value - valueSpentForFactory; _deployL2Contracts( - router, standardGateway, customGateway, wethGateway, inbox, maxGasForContracts, gasPriceBid, fundsRemaining + router, + standardGateway, + customGateway, + wethGateway, + inbox, + maxGasForContracts, + gasPriceBid, + fundsRemaining ); } @@ -206,24 +220,33 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return getCanonicalL1RouterAddress(inbox); } - function _deployL1Contracts(address inbox, address owner) + function _deployL1Contracts(address inbox, address owner, bool isUsingFeeToken) internal - returns (address router, address standardGateway, address customGateway, address wethGateway) + returns ( + address router, + address standardGateway, + address customGateway, + address wethGateway + ) { - address proxyAdmin = address(new ProxyAdmin{ salt: _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox) }()); + address proxyAdmin = + address(new ProxyAdmin{ salt: _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox) }()); // deploy router + address routerTemplate = isUsingFeeToken + ? address(l1Templates.orbitRouterTemplate) + : address(l1Templates.routerTemplate); router = address( new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_ROUTER, inbox) }( - address(routerTemplate), + routerTemplate, proxyAdmin, bytes("") ) ); // deploy and init gateways - standardGateway = _deployL1StandardGateway(proxyAdmin, router, inbox); - customGateway = _deployL1CustomGateway(proxyAdmin, router, inbox, owner); + standardGateway = _deployL1StandardGateway(proxyAdmin, router, inbox, isUsingFeeToken); + customGateway = _deployL1CustomGateway(proxyAdmin, router, inbox, owner, isUsingFeeToken); wethGateway = _deployL1WethGateway(proxyAdmin, router, inbox); // init router @@ -235,15 +258,26 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ProxyAdmin(proxyAdmin).transferOwnership(owner); // emit it - emit OrbitTokenBridgeCreated(inbox, owner, router, standardGateway, customGateway, wethGateway, proxyAdmin); + emit OrbitTokenBridgeCreated( + inbox, owner, router, standardGateway, customGateway, wethGateway, proxyAdmin + ); } - function _deployL1StandardGateway(address proxyAdmin, address router, address inbox) internal returns (address) { + function _deployL1StandardGateway( + address proxyAdmin, + address router, + address inbox, + bool isUsingFeeToken + ) internal returns (address) { + address template = isUsingFeeToken + ? address(l1Templates.orbitStandardGatewayTemplate) + : address(l1Templates.standardGatewayTemplate); + L1ERC20Gateway standardGateway = L1ERC20Gateway( address( new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_STANDARD_GATEWAY, inbox) - }(address(standardGatewayTemplate), proxyAdmin, bytes("")) + }(template, proxyAdmin, bytes("")) ) ); @@ -258,15 +292,22 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return address(standardGateway); } - function _deployL1CustomGateway(address proxyAdmin, address router, address inbox, address owner) - internal - returns (address) - { + function _deployL1CustomGateway( + address proxyAdmin, + address router, + address inbox, + address owner, + bool isUsingFeeToken + ) internal returns (address) { + address template = isUsingFeeToken + ? address(l1Templates.orbitStandardGatewayTemplate) + : address(l1Templates.standardGatewayTemplate); + L1CustomGateway customGateway = L1CustomGateway( address( new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_CUSTOM_GATEWAY, inbox) - }(address(customGatewayTemplate), proxyAdmin, bytes("")) + }(template, proxyAdmin, bytes("")) ) ); @@ -275,18 +316,23 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return address(customGateway); } - function _deployL1WethGateway(address proxyAdmin, address router, address inbox) internal returns (address) { + function _deployL1WethGateway(address proxyAdmin, address router, address inbox) + internal + returns (address) + { L1WethGateway wethGateway = L1WethGateway( payable( address( new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_WETH_GATEWAY, inbox) - }(address(wethGatewayTemplate), proxyAdmin, bytes("")) + }(address(l1Templates.wethGatewayTemplate), proxyAdmin, bytes("")) ) ) ); - wethGateway.initialize(getCanonicalL2WethGatewayAddress(), router, inbox, l1Weth, getCanonicalL2WethAddress()); + wethGateway.initialize( + getCanonicalL2WethGatewayAddress(), router, inbox, l1Weth, getCanonicalL2WethAddress() + ); return address(wethGateway); } @@ -295,7 +341,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // encode L2 factory bytecode bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); - uint256 maxSubmissionCost = IInbox(inbox).calculateRetryableSubmissionFee(deploymentData.length, 0); + uint256 maxSubmissionCost = + IInbox(inbox).calculateRetryableSubmissionFee(deploymentData.length, 0); uint256 value = maxSubmissionCost + gasLimitForL2FactoryDeployment * gasPriceBid; IInbox(inbox).createRetryableTicket{value: value}( address(0), @@ -322,7 +369,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { uint256 availableFunds ) internal { retryableSender.sendRetryable{value: availableFunds}( - RetryableParams(inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxGas, gasPriceBid), + RetryableParams( + inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxGas, gasPriceBid + ), L2TemplateAddresses( l2RouterTemplate, l2StandardGatewayTemplate, @@ -338,20 +387,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function getCanonicalL1RouterAddress(address inbox) public view returns (address) { - address expectedL1ProxyAdminAddress = Create2.computeAddress( - _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox), keccak256(type(ProxyAdmin).creationCode), address(this) - ); - - return Create2.computeAddress( - _getL1Salt(OrbitSalts.L1_ROUTER, inbox), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(routerTemplate, expectedL1ProxyAdminAddress, bytes("")) - ) - ), - address(this) - ); + return + retryableSender.getCanonicalL1RouterAddress(inbox, address(l1Templates.routerTemplate)); } function getCanonicalL2RouterAddress() public view returns (address) { @@ -449,6 +486,19 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); } + function _getFeeToken(address inbox) internal view returns (address) { + address bridge = address(IInbox(inbox).bridge()); + + (bool success, bytes memory feeTokenAddressData) = + bridge.staticcall(abi.encodeWithSelector(IERC20Bridge.nativeToken.selector)); + + if (!success || feeTokenAddressData.length < 32) { + return address(0); + } + + return BytesLib.toAddress(feeTokenAddressData, 12); + } + /** * @notice Compute address of contract deployed using CREATE opcode * @return computed address @@ -501,6 +551,12 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { - return keccak256(abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(retryableSender)))); + return keccak256( + abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(retryableSender))) + ); } } + +interface IERC20Bridge { + function nativeToken() external view returns (address); +} diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index cbdc010e2c..c3cf528428 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -2,8 +2,19 @@ pragma solidity ^0.8.4; import {IInbox} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; -import {L2AtomicTokenBridgeFactory, L2RuntimeCode} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; -import {Initializable, OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { + L2AtomicTokenBridgeFactory, + L2RuntimeCode, + OrbitSalts, + ProxyAdmin +} from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; +import { + Initializable, + OwnableUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; +import {TransparentUpgradeableProxy} from + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; /** * @title Token Bridge Retryable Ticket Sender @@ -54,8 +65,10 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { ) ); - uint256 maxSubmissionCost = IInbox(retryableParams.inbox).calculateRetryableSubmissionFee(data.length, 0); - uint256 retryableValue = maxSubmissionCost + retryableParams.maxGas * retryableParams.gasPriceBid; + uint256 maxSubmissionCost = + IInbox(retryableParams.inbox).calculateRetryableSubmissionFee(data.length, 0); + uint256 retryableValue = + maxSubmissionCost + retryableParams.maxGas * retryableParams.gasPriceBid; _createRetryable(retryableParams, maxSubmissionCost, retryableValue, data); // refund excess value to the deployer @@ -81,6 +94,33 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { data ); } + + function getCanonicalL1RouterAddress(address inbox, address routerTemplate) + public + view + returns (address) + { + address expectedL1ProxyAdminAddress = Create2.computeAddress( + _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox), + keccak256(type(ProxyAdmin).creationCode), + address(this) + ); + + return Create2.computeAddress( + _getL1Salt(OrbitSalts.L1_ROUTER, inbox), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(routerTemplate, expectedL1ProxyAdminAddress, bytes("")) + ) + ), + address(this) + ); + } + + function _getL1Salt(bytes32 prefix, address inbox) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(prefix, inbox)); + } } /** diff --git a/foundry.toml b/foundry.toml index f2022611da..ba6691c9fe 100644 --- a/foundry.toml +++ b/foundry.toml @@ -5,7 +5,7 @@ libs = ["node_modules", "lib"] test = 'test-foundry' cache_path = 'forge-cache' optimizer = true -optimizer_runs = 20000 +optimizer_runs = 100 via_ir = false [fmt] diff --git a/lib/nitro-contracts b/lib/nitro-contracts index f8fad6fd6a..683714aa69 160000 --- a/lib/nitro-contracts +++ b/lib/nitro-contracts @@ -1 +1 @@ -Subproject commit f8fad6fd6a79a45a1a6c8aa3629fd9b82522fa1d +Subproject commit 683714aa69709f9d64aee9370153d80d9670e21a From adf7f4b50c662d3b252c929257b66348ff35d666 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 27 Jul 2023 13:10:57 +0200 Subject: [PATCH 127/163] Add support for fee token based retryables --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 103 +++++++++++++----- .../ethereum/L1TokenBridgeRetryableSender.sol | 79 +++++++++++++- 2 files changed, 151 insertions(+), 31 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 0693a7c859..4459523482 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -5,7 +5,8 @@ import { L1TokenBridgeRetryableSender, L1Addresses, RetryableParams, - L2TemplateAddresses + L2TemplateAddresses, + IERC20Inbox } from "./L1TokenBridgeRetryableSender.sol"; import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol"; import {L1ERC20Gateway} from "./gateway/L1ERC20Gateway.sol"; @@ -180,18 +181,25 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { _deployL1Contracts(inbox, owner, isUsingFeeToken); /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls - uint256 valueSpentForFactory = _deployL2Factory(inbox, gasPriceBid); - uint256 fundsRemaining = msg.value - valueSpentForFactory; - _deployL2Contracts( - router, - standardGateway, - customGateway, - wethGateway, - inbox, - maxGasForContracts, - gasPriceBid, - fundsRemaining - ); + if (isUsingFeeToken) { + _deployL2Factory(inbox, gasPriceBid, isUsingFeeToken); + _deployL2ContractsUsingFeeToken( + router, standardGateway, customGateway, inbox, maxGasForContracts, gasPriceBid + ); + } else { + uint256 valueSpentForFactory = _deployL2Factory(inbox, gasPriceBid, isUsingFeeToken); + uint256 fundsRemaining = msg.value - valueSpentForFactory; + _deployL2ContractsUsingEth( + router, + standardGateway, + customGateway, + wethGateway, + inbox, + maxGasForContracts, + gasPriceBid, + fundsRemaining + ); + } } /** @@ -337,28 +345,46 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return address(wethGateway); } - function _deployL2Factory(address inbox, uint256 gasPriceBid) internal returns (uint256) { + function _deployL2Factory(address inbox, uint256 gasPriceBid, bool isUsingFeeToken) + internal + returns (uint256) + { // encode L2 factory bytecode bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); uint256 maxSubmissionCost = IInbox(inbox).calculateRetryableSubmissionFee(deploymentData.length, 0); - uint256 value = maxSubmissionCost + gasLimitForL2FactoryDeployment * gasPriceBid; - IInbox(inbox).createRetryableTicket{value: value}( - address(0), - 0, - maxSubmissionCost, - msg.sender, - msg.sender, - gasLimitForL2FactoryDeployment, - gasPriceBid, - deploymentData - ); + uint256 retryableFee = maxSubmissionCost + gasLimitForL2FactoryDeployment * gasPriceBid; + + if (isUsingFeeToken) { + IERC20Inbox(inbox).createRetryableTicket( + address(0), + 0, + maxSubmissionCost, + msg.sender, + msg.sender, + gasLimitForL2FactoryDeployment, + gasPriceBid, + retryableFee, + deploymentData + ); + } else { + IInbox(inbox).createRetryableTicket{value: retryableFee}( + address(0), + 0, + maxSubmissionCost, + msg.sender, + msg.sender, + gasLimitForL2FactoryDeployment, + gasPriceBid, + deploymentData + ); + } - return value; + return retryableFee; } - function _deployL2Contracts( + function _deployL2ContractsUsingEth( address l1Router, address l1StandardGateway, address l1CustomGateway, @@ -368,7 +394,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { uint256 gasPriceBid, uint256 availableFunds ) internal { - retryableSender.sendRetryable{value: availableFunds}( + retryableSender.sendRetryableUsingEth{value: availableFunds}( RetryableParams( inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxGas, gasPriceBid ), @@ -386,6 +412,27 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); } + function _deployL2ContractsUsingFeeToken( + address l1Router, + address l1StandardGateway, + address l1CustomGateway, + address inbox, + uint256 maxGas, + uint256 gasPriceBid + ) internal { + retryableSender.sendRetryableUsingFeeToken( + RetryableParams( + inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxGas, gasPriceBid + ), + L2TemplateAddresses( + l1Router, l1StandardGateway, l1CustomGateway, address(0), address(0) + ), + L1Addresses(l1Router, l1StandardGateway, l1CustomGateway, address(0), address(0)), + getCanonicalL2StandardGatewayAddress(), + _getRollupOwner(inbox) + ); + } + function getCanonicalL1RouterAddress(address inbox) public view returns (address) { return retryableSender.getCanonicalL1RouterAddress(inbox, address(l1Templates.routerTemplate)); diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index c3cf528428..1f61f83e35 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -37,7 +37,7 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { * @dev Function will build retryable data, calculate submission cost and retryable value, create retryable * and then refund the remaining funds to original delpoyer. */ - function sendRetryable( + function sendRetryableUsingEth( RetryableParams calldata retryableParams, L2TemplateAddresses calldata l2, L1Addresses calldata l1, @@ -69,7 +69,7 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { IInbox(retryableParams.inbox).calculateRetryableSubmissionFee(data.length, 0); uint256 retryableValue = maxSubmissionCost + retryableParams.maxGas * retryableParams.gasPriceBid; - _createRetryable(retryableParams, maxSubmissionCost, retryableValue, data); + _createRetryableUsingEth(retryableParams, maxSubmissionCost, retryableValue, data); // refund excess value to the deployer uint256 refund = msg.value - retryableValue; @@ -77,7 +77,47 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { if (!success) revert L1TokenBridgeRetryableSender_RefundFailed(); } - function _createRetryable( + /** + * @notice Creates retryable which deploys L2 side of the token bridge. + * @dev Function will build retryable data, calculate submission cost and retryable value, create retryable + * and then refund the remaining funds to original delpoyer. + */ + function sendRetryableUsingFeeToken( + RetryableParams calldata retryableParams, + L2TemplateAddresses calldata l2, + L1Addresses calldata l1, + address l2StandardGatewayAddress, + address rollupOwner + ) external payable onlyOwner { + bytes memory data = abi.encodeCall( + L2AtomicTokenBridgeFactory.deployL2Contracts, + ( + L2RuntimeCode( + l2.routerTemplate.code, + l2.standardGatewayTemplate.code, + l2.customGatewayTemplate.code, + "", + "" + ), + l1.router, + l1.standardGateway, + l1.customGateway, + address(0), + address(0), + l2StandardGatewayAddress, + rollupOwner + ) + ); + + uint256 maxSubmissionCost = + IInbox(retryableParams.inbox).calculateRetryableSubmissionFee(data.length, 0); + uint256 retryableFee = + maxSubmissionCost + retryableParams.maxGas * retryableParams.gasPriceBid; + + _createRetryableUsingFeeToken(retryableParams, maxSubmissionCost, retryableFee, data); + } + + function _createRetryableUsingEth( RetryableParams calldata retryableParams, uint256 maxSubmissionCost, uint256 value, @@ -95,6 +135,25 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { ); } + function _createRetryableUsingFeeToken( + RetryableParams calldata retryableParams, + uint256 maxSubmissionCost, + uint256 retryableFee, + bytes memory data + ) internal { + IERC20Inbox(retryableParams.inbox).createRetryableTicket( + retryableParams.target, + 0, + maxSubmissionCost, + retryableParams.excessFeeRefundAddress, + retryableParams.callValueRefundAddress, + retryableParams.maxGas, + retryableParams.gasPriceBid, + retryableFee, + data + ); + } + function getCanonicalL1RouterAddress(address inbox, address routerTemplate) public view @@ -156,3 +215,17 @@ struct L1Addresses { address wethGateway; address weth; } + +interface IERC20Inbox { + function createRetryableTicket( + address to, + uint256 l2CallValue, + uint256 maxSubmissionCost, + address excessFeeRefundAddress, + address callValueRefundAddress, + uint256 gasLimit, + uint256 maxFeePerGas, + uint256 tokenTotalFeeAmount, + bytes calldata data + ) external returns (uint256); +} From db4a222104f8df2791153fce5aba207e972ff69b Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 27 Jul 2023 13:54:33 +0200 Subject: [PATCH 128/163] Move fee tokens to inbox to pay for retryables --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 30 ++++++++++++++----- .../ethereum/L1TokenBridgeRetryableSender.sol | 12 ++++---- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 4459523482..d1b76af8fd 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -6,7 +6,9 @@ import { L1Addresses, RetryableParams, L2TemplateAddresses, - IERC20Inbox + IERC20Inbox, + IERC20, + SafeERC20 } from "./L1TokenBridgeRetryableSender.sol"; import {L1GatewayRouter} from "./gateway/L1GatewayRouter.sol"; import {L1ERC20Gateway} from "./gateway/L1ERC20Gateway.sol"; @@ -41,6 +43,8 @@ import { * @dev Throughout the contract terms L1 and L2 are used, but those can be considered as base (N) chain and child (N+1) chain */ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { + using SafeERC20 for IERC20; + error L1AtomicTokenBridgeCreator_OnlyRollupOwner(); error L1AtomicTokenBridgeCreator_InvalidRouterAddr(); error L1AtomicTokenBridgeCreator_TemplatesNotSet(); @@ -352,15 +356,16 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // encode L2 factory bytecode bytes memory deploymentData = _creationCodeFor(l2TokenBridgeFactoryTemplate.code); - uint256 maxSubmissionCost = - IInbox(inbox).calculateRetryableSubmissionFee(deploymentData.length, 0); - uint256 retryableFee = maxSubmissionCost + gasLimitForL2FactoryDeployment * gasPriceBid; - if (isUsingFeeToken) { + // transfer fee tokens to inbox to pay for 1st retryable + address feeToken = _getFeeToken(inbox); + uint256 retryableFee = gasLimitForL2FactoryDeployment * gasPriceBid; + IERC20(feeToken).safeTransferFrom(msg.sender, inbox, retryableFee); + IERC20Inbox(inbox).createRetryableTicket( address(0), 0, - maxSubmissionCost, + 0, msg.sender, msg.sender, gasLimitForL2FactoryDeployment, @@ -368,7 +373,12 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { retryableFee, deploymentData ); + return 0; } else { + uint256 maxSubmissionCost = + IInbox(inbox).calculateRetryableSubmissionFee(deploymentData.length, 0); + uint256 retryableFee = maxSubmissionCost + gasLimitForL2FactoryDeployment * gasPriceBid; + IInbox(inbox).createRetryableTicket{value: retryableFee}( address(0), 0, @@ -379,9 +389,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { gasPriceBid, deploymentData ); + return retryableFee; } - - return retryableFee; } function _deployL2ContractsUsingEth( @@ -420,6 +429,11 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { uint256 maxGas, uint256 gasPriceBid ) internal { + // transfer fee tokens to inbox to pay for 2nd retryable + address feeToken = _getFeeToken(inbox); + uint256 fee = maxGas * gasPriceBid; + IERC20(feeToken).safeTransferFrom(msg.sender, inbox, fee); + retryableSender.sendRetryableUsingFeeToken( RetryableParams( inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxGas, gasPriceBid diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index 1f61f83e35..1e91ce7d4e 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -15,6 +15,8 @@ import { import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /** * @title Token Bridge Retryable Ticket Sender @@ -109,12 +111,9 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { ) ); - uint256 maxSubmissionCost = - IInbox(retryableParams.inbox).calculateRetryableSubmissionFee(data.length, 0); - uint256 retryableFee = - maxSubmissionCost + retryableParams.maxGas * retryableParams.gasPriceBid; + uint256 retryableFee = retryableParams.maxGas * retryableParams.gasPriceBid; - _createRetryableUsingFeeToken(retryableParams, maxSubmissionCost, retryableFee, data); + _createRetryableUsingFeeToken(retryableParams, retryableFee, data); } function _createRetryableUsingEth( @@ -137,14 +136,13 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { function _createRetryableUsingFeeToken( RetryableParams calldata retryableParams, - uint256 maxSubmissionCost, uint256 retryableFee, bytes memory data ) internal { IERC20Inbox(retryableParams.inbox).createRetryableTicket( retryableParams.target, 0, - maxSubmissionCost, + 0, retryableParams.excessFeeRefundAddress, retryableParams.callValueRefundAddress, retryableParams.maxGas, From a0029a84e02e8f553913ba2d327241921aab121e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 27 Jul 2023 14:03:49 +0200 Subject: [PATCH 129/163] Move getter for canonical L1 router address to L1 creator --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 62 +++++++++++++------ .../ethereum/L1AtomicTokenBridgeCreator.sol | 18 +++++- .../ethereum/L1TokenBridgeRetryableSender.sol | 27 -------- 3 files changed, 60 insertions(+), 47 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 6d81b1d6f4..51bdd941fd 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -33,13 +33,21 @@ contract L2AtomicTokenBridgeFactory { address rollupOwner ) external { // create proxyAdmin which will be used for all contracts - address proxyAdmin = address(new ProxyAdmin{ salt: _getL2Salt(OrbitSalts.L2_PROXY_ADMIN) }()); + address proxyAdmin = + address(new ProxyAdmin{ salt: _getL2Salt(OrbitSalts.L2_PROXY_ADMIN) }()); // deploy router/gateways - address router = _deployRouter(l2Code.router, l1Router, l2StandardGatewayCanonicalAddress, proxyAdmin); + address router = + _deployRouter(l2Code.router, l1Router, l2StandardGatewayCanonicalAddress, proxyAdmin); _deployStandardGateway(l2Code.standardGateway, l1StandardGateway, router, proxyAdmin); _deployCustomGateway(l2Code.customGateway, l1CustomGateway, router, proxyAdmin); - _deployWethGateway(l2Code.wethGateway, l2Code.aeWeth, l1WethGateway, l1Weth, router, proxyAdmin); + + // fee token based creator will provide address(0) as WETH is not used in ERC20-based chains + if (l1WethGateway != address(0)) { + _deployWethGateway( + l2Code.wethGateway, l2Code.aeWeth, l1WethGateway, l1Weth, router, proxyAdmin + ); + } // transfer ownership to rollup's owner ProxyAdmin(proxyAdmin).transferOwnership(rollupOwner); @@ -61,7 +69,8 @@ contract L2AtomicTokenBridgeFactory { ); // create L2 router logic and upgrade - address routerLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), _creationCodeFor(runtimeCode)); + address routerLogic = + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), _creationCodeFor(runtimeCode)); ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalRouter), routerLogic); // init @@ -90,9 +99,12 @@ contract L2AtomicTokenBridgeFactory { ); // create L2 standard gateway logic and upgrade - address stdGatewayLogic = - Create2.deploy(0, _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), _creationCodeFor(runtimeCode)); - ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalStdGateway), stdGatewayLogic); + address stdGatewayLogic = Create2.deploy( + 0, _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), _creationCodeFor(runtimeCode) + ); + ProxyAdmin(proxyAdmin).upgrade( + ITransparentUpgradeableProxy(canonicalStdGateway), stdGatewayLogic + ); // create beacon StandardArbERC20 standardArbERC20 = new StandardArbERC20{ @@ -107,7 +119,9 @@ contract L2AtomicTokenBridgeFactory { // init contracts beaconProxyFactory.initialize(address(beacon)); - L2ERC20Gateway(canonicalStdGateway).initialize(l1StandardGateway, router, address(beaconProxyFactory)); + L2ERC20Gateway(canonicalStdGateway).initialize( + l1StandardGateway, router, address(beaconProxyFactory) + ); } function _deployCustomGateway( @@ -130,9 +144,12 @@ contract L2AtomicTokenBridgeFactory { ); // create L2 custom gateway logic and upgrade - address customGatewayLogicAddress = - Create2.deploy(0, _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), _creationCodeFor(runtimeCode)); - ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalCustomGateway), customGatewayLogicAddress); + address customGatewayLogicAddress = Create2.deploy( + 0, _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), _creationCodeFor(runtimeCode) + ); + ProxyAdmin(proxyAdmin).upgrade( + ITransparentUpgradeableProxy(canonicalCustomGateway), customGatewayLogicAddress + ); // init L2GatewayRouter(canonicalCustomGateway).initialize(l1CustomGateway, router); @@ -156,8 +173,9 @@ contract L2AtomicTokenBridgeFactory { ); // create L2WETH logic and upgrade - address l2WethLogic = - Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_LOGIC), _creationCodeFor(aeWethRuntimeCode)); + address l2WethLogic = Create2.deploy( + 0, _getL2Salt(OrbitSalts.L2_WETH_LOGIC), _creationCodeFor(aeWethRuntimeCode) + ); ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalL2Weth), l2WethLogic); // canonical L2 WETH gateway with dummy logic @@ -172,9 +190,14 @@ contract L2AtomicTokenBridgeFactory { ); // create L2WETH gateway logic and upgrade - address l2WethGatewayLogic = - Create2.deploy(0, _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), _creationCodeFor(wethGatewayRuntimeCode)); - ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalL2WethGateway), l2WethGatewayLogic); + address l2WethGatewayLogic = Create2.deploy( + 0, + _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), + _creationCodeFor(wethGatewayRuntimeCode) + ); + ProxyAdmin(proxyAdmin).upgrade( + ITransparentUpgradeableProxy(canonicalL2WethGateway), l2WethGatewayLogic + ); // init gateway L2WethGateway(payable(canonicalL2WethGateway)).initialize( @@ -182,7 +205,9 @@ contract L2AtomicTokenBridgeFactory { ); // init L2Weth - aeWETH(payable(canonicalL2Weth)).initialize("WETH", "WETH", 18, canonicalL2WethGateway, l1Weth); + aeWETH(payable(canonicalL2Weth)).initialize( + "WETH", "WETH", 18, canonicalL2WethGateway, l1Weth + ); } function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { @@ -240,7 +265,8 @@ library OrbitSalts { bytes32 public constant L2_PROXY_ADMIN = keccak256(bytes("OrbitL2ProxyAdmin")); bytes32 public constant L2_ROUTER_LOGIC = keccak256(bytes("OrbitL2GatewayRouterLogic")); bytes32 public constant L2_ROUTER = keccak256(bytes("OrbitL2GatewayRouterProxy")); - bytes32 public constant L2_STANDARD_GATEWAY_LOGIC = keccak256(bytes("OrbitL2StandardGatewayLogic")); + bytes32 public constant L2_STANDARD_GATEWAY_LOGIC = + keccak256(bytes("OrbitL2StandardGatewayLogic")); bytes32 public constant L2_STANDARD_GATEWAY = keccak256(bytes("OrbitL2StandardGatewayProxy")); bytes32 public constant L2_CUSTOM_GATEWAY_LOGIC = keccak256(bytes("OrbitL2CustomGatewayLogic")); bytes32 public constant L2_CUSTOM_GATEWAY = keccak256(bytes("OrbitL2CustomGatewayProxy")); diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index d1b76af8fd..595ac50247 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -448,8 +448,22 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function getCanonicalL1RouterAddress(address inbox) public view returns (address) { - return - retryableSender.getCanonicalL1RouterAddress(inbox, address(l1Templates.routerTemplate)); + address expectedL1ProxyAdminAddress = Create2.computeAddress( + _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox), + keccak256(type(ProxyAdmin).creationCode), + address(this) + ); + + return Create2.computeAddress( + _getL1Salt(OrbitSalts.L1_ROUTER, inbox), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(l1Templates.routerTemplate, expectedL1ProxyAdminAddress, bytes("")) + ) + ), + address(this) + ); } function getCanonicalL2RouterAddress() public view returns (address) { diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index 1e91ce7d4e..94d42ae6f3 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -151,33 +151,6 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { data ); } - - function getCanonicalL1RouterAddress(address inbox, address routerTemplate) - public - view - returns (address) - { - address expectedL1ProxyAdminAddress = Create2.computeAddress( - _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox), - keccak256(type(ProxyAdmin).creationCode), - address(this) - ); - - return Create2.computeAddress( - _getL1Salt(OrbitSalts.L1_ROUTER, inbox), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(routerTemplate, expectedL1ProxyAdminAddress, bytes("")) - ) - ), - address(this) - ); - } - - function _getL1Salt(bytes32 prefix, address inbox) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(prefix, inbox)); - } } /** From f399dfa094b9f81512a900d2c671a60b6e473c20 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 27 Jul 2023 14:08:54 +0200 Subject: [PATCH 130/163] Init retryable sender from init of L1 creator --- contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 595ac50247..217b78c86e 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -109,8 +109,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { function initialize(L1TokenBridgeRetryableSender _retryableSender) public initializer { __Ownable_init(); - // deploy retryableSender only once - its address will be part of salt for L2 contracts + // store retryable sender and initialize it. This contract will be set as owner retryableSender = _retryableSender; + retryableSender.initialize(); canonicalL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); From c6ba878362f4fc764890f123a21c46f9cc61a29e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 27 Jul 2023 14:27:07 +0200 Subject: [PATCH 131/163] Adjust script for deploying creator --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 14 ++--- scripts/atomicTokenBridgeDeployer.ts | 58 +++++++++++++++++-- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 217b78c86e..9772e6f35b 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -66,9 +66,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { L1ERC20Gateway standardGatewayTemplate; L1CustomGateway customGatewayTemplate; L1WethGateway wethGatewayTemplate; - L1OrbitGatewayRouter orbitRouterTemplate; - L1OrbitERC20Gateway orbitStandardGatewayTemplate; - L1OrbitCustomGateway orbitCustomGatewayTemplate; + L1OrbitGatewayRouter feeTokenBasedRouterTemplate; + L1OrbitERC20Gateway feeTokenBasedStandardGatewayTemplate; + L1OrbitCustomGateway feeTokenBasedCustomGatewayTemplate; } // non-canonical router registry @@ -247,7 +247,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // deploy router address routerTemplate = isUsingFeeToken - ? address(l1Templates.orbitRouterTemplate) + ? address(l1Templates.feeTokenBasedRouterTemplate) : address(l1Templates.routerTemplate); router = address( new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_ROUTER, inbox) }( @@ -283,7 +283,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { bool isUsingFeeToken ) internal returns (address) { address template = isUsingFeeToken - ? address(l1Templates.orbitStandardGatewayTemplate) + ? address(l1Templates.feeTokenBasedStandardGatewayTemplate) : address(l1Templates.standardGatewayTemplate); L1ERC20Gateway standardGateway = L1ERC20Gateway( @@ -313,8 +313,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { bool isUsingFeeToken ) internal returns (address) { address template = isUsingFeeToken - ? address(l1Templates.orbitStandardGatewayTemplate) - : address(l1Templates.standardGatewayTemplate); + ? address(l1Templates.feeTokenBasedCustomGatewayTemplate) + : address(l1Templates.customGatewayTemplate); L1CustomGateway customGateway = L1CustomGateway( address( diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index d3d39f8732..e212b3276b 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -14,6 +14,10 @@ import { L1WethGateway__factory, TransparentUpgradeableProxy__factory, ProxyAdmin__factory, + L1TokenBridgeRetryableSender__factory, + L1OrbitERC20Gateway__factory, + L1OrbitCustomGateway__factory, + L1OrbitGatewayRouter__factory, } from '../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { @@ -215,9 +219,31 @@ export const deployL1TokenBridgeCreator = async ( const l1TokenBridgeCreator = L1AtomicTokenBridgeCreator__factory.connect( l1TokenBridgeCreatorProxy.address, + l1Deployer.provider! + ) + + /// deploy retryable sender behind proxy + const retryableSenderLogic = await new L1TokenBridgeRetryableSender__factory( + l1Deployer + ).deploy() + await retryableSenderLogic.deployed() + + const retryableSenderProxy = await new TransparentUpgradeableProxy__factory( + l1Deployer + ).deploy( + retryableSenderLogic.address, + l1TokenBridgeCreatorProxyAdmin.address, + '0x' + ) + await retryableSenderProxy.deployed() + + const retryableSender = L1TokenBridgeRetryableSender__factory.connect( + retryableSenderProxy.address, l1Deployer ) - await (await l1TokenBridgeCreator.initialize()).wait() + + /// init creator + await (await l1TokenBridgeCreator.initialize(retryableSender.address)).wait() /// deploy L1 logic contracts const routerTemplate = await new L1GatewayRouter__factory(l1Deployer).deploy() @@ -238,6 +264,31 @@ export const deployL1TokenBridgeCreator = async ( ).deploy() await wethGatewayTemplate.deployed() + const feeTokenBasedRouterTemplate = await new L1OrbitGatewayRouter__factory( + l1Deployer + ).deploy() + await feeTokenBasedRouterTemplate.deployed() + + const feeTokenBasedStandardGatewayTemplate = + await new L1OrbitERC20Gateway__factory(l1Deployer).deploy() + await feeTokenBasedStandardGatewayTemplate.deployed() + + const feeTokenBasedCustomGatewayTemplate = + await new L1OrbitCustomGateway__factory(l1Deployer).deploy() + await feeTokenBasedCustomGatewayTemplate.deployed() + + const l1Templates = { + routerTemplate: routerTemplate.address, + standardGatewayTemplate: standardGatewayTemplate.address, + customGatewayTemplate: customGatewayTemplate.address, + wethGatewayTemplate: wethGatewayTemplate.address, + feeTokenBasedRouterTemplate: feeTokenBasedRouterTemplate.address, + feeTokenBasedStandardGatewayTemplate: + feeTokenBasedStandardGatewayTemplate.address, + feeTokenBasedCustomGatewayTemplate: + feeTokenBasedCustomGatewayTemplate.address, + } + /// deploy L2 contracts as placeholders on L1 const l2TokenBridgeFactoryOnL1 = @@ -275,10 +326,7 @@ export const deployL1TokenBridgeCreator = async ( await ( await l1TokenBridgeCreator.setTemplates( - routerTemplate.address, - standardGatewayTemplate.address, - customGatewayTemplate.address, - wethGatewayTemplate.address, + l1Templates, l2TokenBridgeFactoryOnL1.address, l2GatewayRouterOnL1.address, l2StandardGatewayAddressOnL1.address, From 9f0ca76d62c8dfb3aaa23ee3e5fc70c81749cb4c Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 28 Jul 2023 13:07:54 +0200 Subject: [PATCH 132/163] Fix L1 router address calculation --- .../tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol | 7 ++++++- contracts/tokenbridge/libraries/IERC20Bridge.sol | 2 +- lib/nitro-contracts | 2 +- package.json | 1 - scripts/atomicTokenBridgeDeployer.ts | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 9772e6f35b..0f76fac042 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -455,12 +455,17 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address(this) ); + bool isUsingFeeToken = _getFeeToken(inbox) != address(0); + address template = isUsingFeeToken + ? address(l1Templates.feeTokenBasedRouterTemplate) + : address(l1Templates.routerTemplate); + return Create2.computeAddress( _getL1Salt(OrbitSalts.L1_ROUTER, inbox), keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(l1Templates.routerTemplate, expectedL1ProxyAdminAddress, bytes("")) + abi.encode(template, expectedL1ProxyAdminAddress, bytes("")) ) ), address(this) diff --git a/contracts/tokenbridge/libraries/IERC20Bridge.sol b/contracts/tokenbridge/libraries/IERC20Bridge.sol index 6a093d74d2..d850579311 100644 --- a/contracts/tokenbridge/libraries/IERC20Bridge.sol +++ b/contracts/tokenbridge/libraries/IERC20Bridge.sol @@ -7,5 +7,5 @@ interface IERC20Bridge { /** * @dev token that is escrowed in bridge on L1 side and minted on L2 as native currency. Also fees are paid in this token. */ - function nativeToken() external returns (address); + function nativeToken() external view returns (address); } diff --git a/lib/nitro-contracts b/lib/nitro-contracts index 683714aa69..1aa6599566 160000 --- a/lib/nitro-contracts +++ b/lib/nitro-contracts @@ -1 +1 @@ -Subproject commit 683714aa69709f9d64aee9370153d80d9670e21a +Subproject commit 1aa65995664346a3ad5e874fd3581a4d6f34b734 diff --git a/package.json b/package.json index 29cf1644bd..1be7056146 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "test:unit": "forge test", "test:e2e:local-env": "yarn hardhat test test-e2e/*", "test:storage": "./scripts/storage_layout_test.bash", - "deploy:orbit-tokenbridge:script": "ts-node ./scripts/local-deployment/orbitTokenBridgeDeployer.ts", "deploy:local:token-bridge": "ts-node ./scripts/local-deployment/deploy.ts", "deploy:goerli:token-bridge-creator": "ts-node ./scripts/goerli-deployment/deployTokenBridgeCreator.ts", "create:goerli:token-bridge": "ts-node ./scripts/goerli-deployment/createTokenBridge.ts", diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index e212b3276b..d6aa0ae1b3 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -219,7 +219,7 @@ export const deployL1TokenBridgeCreator = async ( const l1TokenBridgeCreator = L1AtomicTokenBridgeCreator__factory.connect( l1TokenBridgeCreatorProxy.address, - l1Deployer.provider! + l1Deployer ) /// deploy retryable sender behind proxy From 43542bbd6344453832da3f100bb8f51c7181c761 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 28 Jul 2023 17:04:31 +0200 Subject: [PATCH 133/163] Send correct bytecode to L2 --- .../tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 0f76fac042..ee4ff42f4d 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -260,7 +260,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // deploy and init gateways standardGateway = _deployL1StandardGateway(proxyAdmin, router, inbox, isUsingFeeToken); customGateway = _deployL1CustomGateway(proxyAdmin, router, inbox, owner, isUsingFeeToken); - wethGateway = _deployL1WethGateway(proxyAdmin, router, inbox); + wethGateway = isUsingFeeToken ? address(0) : _deployL1WethGateway(proxyAdmin, router, inbox); // init router L1GatewayRouter(router).initialize( @@ -440,7 +440,11 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxGas, gasPriceBid ), L2TemplateAddresses( - l1Router, l1StandardGateway, l1CustomGateway, address(0), address(0) + l2RouterTemplate, + l2StandardGatewayTemplate, + l2CustomGatewayTemplate, + address(0), + address(0) ), L1Addresses(l1Router, l1StandardGateway, l1CustomGateway, address(0), address(0)), getCanonicalL2StandardGatewayAddress(), From 0e9cc76f0b4d94c5e8eb1b89d324d227501e6c60 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 28 Jul 2023 17:06:44 +0200 Subject: [PATCH 134/163] Update test script --- scripts/atomicTokenBridgeDeployer.ts | 58 ++++++++++++++++--- .../goerli-deployment/createTokenBridge.ts | 4 +- test-e2e/tokenBridgeDeploymentTest.ts | 41 +++++++++---- 3 files changed, 83 insertions(+), 20 deletions(-) diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index d6aa0ae1b3..ed0dc31fec 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -18,6 +18,9 @@ import { L1OrbitERC20Gateway__factory, L1OrbitCustomGateway__factory, L1OrbitGatewayRouter__factory, + IInbox__factory, + IERC20Bridge__factory, + IERC20__factory, } from '../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { @@ -54,6 +57,7 @@ export const createTokenBridge = async ( l1Signer, l2Provider ) + const maxGasForFactory = await l1TokenBridgeCreator.gasLimitForL2FactoryDeployment() const maxSubmissionCostForFactory = deployFactoryGasParams.maxSubmissionCost @@ -86,7 +90,7 @@ export const createTokenBridge = async ( const maxSubmissionCostForContracts = deployFactoryGasParams.maxSubmissionCost.mul(2) - let retryableValue = maxSubmissionCostForFactory + let retryableFee = maxSubmissionCostForFactory .add(maxSubmissionCostForContracts) .add(maxGasForFactory.mul(gasPrice)) .add(maxGasForContracts.mul(gasPrice)) @@ -97,16 +101,30 @@ export const createTokenBridge = async ( l1Signer.provider! ).inbox() + // if fee token is used approve the fee + const feeToken = await _getFeeToken(inbox, l1Signer.provider!) + if (feeToken != ethers.constants.AddressZero) { + await ( + await IERC20__factory.connect(feeToken, l1Signer).approve( + l1TokenBridgeCreator.address, + retryableFee + ) + ).wait() + retryableFee = BigNumber.from(0) + } + /// do it - create token bridge const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( inbox, maxGasForContracts, gasPrice, - { value: retryableValue } + { value: retryableFee } ) ).wait() + console.log('Deployment TX:', receipt.transactionHash) + /// wait for execution of both tickets const l1TxReceipt = new L1TransactionReceipt(receipt) const messages = await l1TxReceipt.getL1ToL2Messages(l2Provider) @@ -162,12 +180,18 @@ export const createTokenBridge = async ( const beaconProxyFactory = await l2StandardGateway.beaconProxyFactory() const l2CustomGateway = await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress() - const l2WethGateway = L2WethGateway__factory.connect( - await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(), - l2Provider - ) + + const isUsingFeeToken = feeToken != ethers.constants.AddressZero + const l2WethGateway = isUsingFeeToken + ? ethers.constants.AddressZero + : L2WethGateway__factory.connect( + await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(), + l2Provider + ).address const l1Weth = await l1TokenBridgeCreator.l1Weth() - const l2Weth = await l1TokenBridgeCreator.getCanonicalL2WethAddress() + const l2Weth = isUsingFeeToken + ? ethers.constants.AddressZero + : await l1TokenBridgeCreator.getCanonicalL2WethAddress() const l2ProxyAdmin = await l1TokenBridgeCreator.canonicalL2ProxyAdminAddress() return { @@ -179,7 +203,7 @@ export const createTokenBridge = async ( l2Router, l2StandardGateway: l2StandardGateway.address, l2CustomGateway, - l2WethGateway: l2WethGateway.address, + l2WethGateway, l1Weth, l2Weth, beaconProxyFactory, @@ -385,6 +409,24 @@ export const getParsedLogs = ( return parsedLogs } +const _getFeeToken = async ( + inbox: string, + l1Provider: ethers.providers.Provider +) => { + const bridge = await IInbox__factory.connect(inbox, l1Provider).bridge() + + let feeToken = ethers.constants.AddressZero + + try { + feeToken = await IERC20Bridge__factory.connect( + bridge, + l1Provider + ).nativeToken() + } catch {} + + return feeToken +} + export function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)) } diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts index c5aca52f95..830cea8f88 100644 --- a/scripts/goerli-deployment/createTokenBridge.ts +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -14,7 +14,7 @@ export const envVars = { childChainRpc: process.env['ORBIT_RPC'] as string, } -const L1_TOKEN_BRIDGE_CREATOR = '0xAd146718D61dc3024428ED7Ed11ade741A37EA38' +const L1_TOKEN_BRIDGE_CREATOR = '0x4Ba3aC2a2fEf26eAA6d05D71B79fde08Cb3078a9' /** * Steps: @@ -47,12 +47,12 @@ export const createTokenBridgeOnGoerli = async (rollupAddress: string) => { rollupAddress ) - // create token bridge const l1TokenBridgeCreator = L1AtomicTokenBridgeCreator__factory.connect( L1_TOKEN_BRIDGE_CREATOR, l1Deployer ) + // create token bridge const deployedContracts = await createTokenBridge( l1Deployer, l2Provider, diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index bc10e4f482..395f68aa4f 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -2,6 +2,8 @@ import { L1Network, L2Network, getL1Network, getL2Network } from '@arbitrum/sdk' import { JsonRpcProvider } from '@ethersproject/providers' import { BeaconProxyFactory__factory, + IERC20Bridge__factory, + IInbox__factory, IOwnable, IOwnable__factory, L1CustomGateway, @@ -82,12 +84,17 @@ describe('tokenBridge', () => { ) ) - await checkL1WethGatewayInitialization( - L1WethGateway__factory.connect( - _l2Network.tokenBridge.l1WethGateway, - l1Provider - ) + const usingFeeToken = await isUsingFeeToken( + _l2Network.ethBridge.inbox, + l1Provider ) + if (!usingFeeToken) + await checkL1WethGatewayInitialization( + L1WethGateway__factory.connect( + _l2Network.tokenBridge.l1WethGateway, + l1Provider + ) + ) //// L2 checks @@ -136,12 +143,14 @@ describe('tokenBridge', () => { ) ) - await checkL2WethGatewayInitialization( - L2WethGateway__factory.connect( - _l2Network.tokenBridge.l2WethGateway, - l2Provider + if (!usingFeeToken) { + await checkL2WethGatewayInitialization( + L2WethGateway__factory.connect( + _l2Network.tokenBridge.l2WethGateway, + l2Provider + ) ) - ) + } }) }) @@ -404,3 +413,15 @@ export const getProvidersAndSetupNetworks = async (setupConfig: { } } } + +async function isUsingFeeToken(inbox: string, l1Provider: JsonRpcProvider) { + const bridge = await IInbox__factory.connect(inbox, l1Provider).bridge() + + try { + await IERC20Bridge__factory.connect(bridge, l1Provider).nativeToken() + } catch { + return false + } + + return true +} From 46647a99d9c34a6c8cf23dddbf60e65046e5e907 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 28 Jul 2023 17:10:46 +0200 Subject: [PATCH 135/163] Remove unnecessary scripts --- package.json | 2 +- ...s => deployCreatorAndCreateTokenBridge.ts} | 0 .../orbitTokenBridgeDeployer.ts | 259 ------------ .../local-deployment/tokenBridgeDeployer.ts | 392 ------------------ 4 files changed, 1 insertion(+), 652 deletions(-) rename scripts/local-deployment/{deploy.ts => deployCreatorAndCreateTokenBridge.ts} (100%) delete mode 100644 scripts/local-deployment/orbitTokenBridgeDeployer.ts delete mode 100644 scripts/local-deployment/tokenBridgeDeployer.ts diff --git a/package.json b/package.json index 1be7056146..5edc0b423d 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test:unit": "forge test", "test:e2e:local-env": "yarn hardhat test test-e2e/*", "test:storage": "./scripts/storage_layout_test.bash", - "deploy:local:token-bridge": "ts-node ./scripts/local-deployment/deploy.ts", + "deploy:local:token-bridge": "ts-node ./scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts", "deploy:goerli:token-bridge-creator": "ts-node ./scripts/goerli-deployment/deployTokenBridgeCreator.ts", "create:goerli:token-bridge": "ts-node ./scripts/goerli-deployment/createTokenBridge.ts", "test:tokenbridge:deployment": "hardhat test test-e2e/tokenBridgeDeploymentTest.ts", diff --git a/scripts/local-deployment/deploy.ts b/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts similarity index 100% rename from scripts/local-deployment/deploy.ts rename to scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts diff --git a/scripts/local-deployment/orbitTokenBridgeDeployer.ts b/scripts/local-deployment/orbitTokenBridgeDeployer.ts deleted file mode 100644 index f76ce18f1c..0000000000 --- a/scripts/local-deployment/orbitTokenBridgeDeployer.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { Contract, ContractFactory, Signer, constants, ethers } from 'ethers' -import { - BeaconProxyFactory__factory, - ERC20__factory, - L1OrbitCustomGateway__factory, - L1OrbitERC20Gateway__factory, - L1OrbitGatewayRouter__factory, - L2CustomGateway__factory, - L2ERC20Gateway__factory, - L2GatewayRouter__factory, - ProxyAdmin__factory, - StandardArbERC20__factory, - TransparentUpgradeableProxy__factory, - UpgradeableBeacon__factory, -} from '../../build/types' -import { setupOrbitTokenBridge, sleep } from './testSetup' -import * as fs from 'fs' - -/** - * Deploy all the L1 and L2 contracts and do the initialization. - * - * @param l1Signer - * @param l2Signer - * @param inboxAddress - * @param nativeTokenAddress - * @returns - */ -export const deployOrbitTokenBridgeAndInit = async ( - l1Signer: Signer, - l2Signer: Signer, - inboxAddress: string, - nativeTokenAddress: string -) => { - console.log('deploying l1 side') - const l1 = await deployTokenBridgeL1Side(l1Signer) - - // fund L2 deployer so contracts can be deployed - await bridgeFundsToL2Deployer(l1Signer, inboxAddress, nativeTokenAddress) - - console.log('deploying l2 side') - const l2 = await deployTokenBridgeL2Side(l2Signer) - - console.log('initialising L2') - await l2.router.initialize(l1.router.address, l2.standardGateway.address) - await l2.beaconProxyFactory.initialize(l2.beacon.address) - await ( - await l2.standardGateway.initialize( - l1.standardGateway.address, - l2.router.address, - l2.beaconProxyFactory.address - ) - ).wait() - await ( - await l2.customGateway.initialize( - l1.customGateway.address, - l2.router.address - ) - ).wait() - - console.log('initialising L1') - await ( - await l1.router.initialize( - await l1Signer.getAddress(), - l1.standardGateway.address, - constants.AddressZero, - l2.router.address, - inboxAddress - ) - ).wait() - - await ( - await l1.standardGateway.initialize( - l2.standardGateway.address, - l1.router.address, - inboxAddress, - await l2.beaconProxyFactory.cloneableProxyHash(), - l2.beaconProxyFactory.address - ) - ).wait() - await ( - await l1.customGateway.initialize( - l2.customGateway.address, - l1.router.address, - inboxAddress, - await l1Signer.getAddress() - ) - ).wait() - - return { l1, l2 } -} - -const deployTokenBridgeL1Side = async (deployer: Signer) => { - const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() - await proxyAdmin.deployed() - console.log('proxyAdmin', proxyAdmin.address) - - const router = await deployContractBehindProxy( - deployer, - L1OrbitGatewayRouter__factory, - proxyAdmin.address, - L1OrbitGatewayRouter__factory.connect - ) - console.log('router', router.address) - - const standardGateway = await deployContractBehindProxy( - deployer, - L1OrbitERC20Gateway__factory, - proxyAdmin.address, - L1OrbitERC20Gateway__factory.connect - ) - console.log('standardGateway', standardGateway.address) - - const customGateway = await deployContractBehindProxy( - deployer, - L1OrbitCustomGateway__factory, - proxyAdmin.address, - L1OrbitCustomGateway__factory.connect - ) - console.log('customGateway', standardGateway.address) - - return { - proxyAdmin, - router, - standardGateway, - customGateway, - } -} - -const deployTokenBridgeL2Side = async (deployer: Signer) => { - const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() - await proxyAdmin.deployed() - - const router = await deployContractBehindProxy( - deployer, - L2GatewayRouter__factory, - proxyAdmin.address, - L2GatewayRouter__factory.connect - ) - - const standardGateway = await deployContractBehindProxy( - deployer, - L2ERC20Gateway__factory, - proxyAdmin.address, - L2ERC20Gateway__factory.connect - ) - - const customGateway = await deployContractBehindProxy( - deployer, - L2CustomGateway__factory, - proxyAdmin.address, - L2CustomGateway__factory.connect - ) - - const standardArbERC20 = await new StandardArbERC20__factory( - deployer - ).deploy() - await standardArbERC20.deployed() - - const beacon = await new UpgradeableBeacon__factory(deployer).deploy( - standardArbERC20.address - ) - await beacon.deployed() - - const beaconProxyFactory = await new BeaconProxyFactory__factory( - deployer - ).deploy() - await beaconProxyFactory.deployed() - - return { - proxyAdmin, - router, - standardGateway, - customGateway, - standardArbERC20, - beacon, - beaconProxyFactory, - } -} - -const bridgeFundsToL2Deployer = async ( - l1Signer: Signer, - inboxAddress: string, - nativeTokenAddress: string -) => { - console.log('fund L2 deployer') - - const depositAmount = ethers.utils.parseUnits('1000', 'ether') - - // approve tokens to bridge - await ( - await ERC20__factory.connect(nativeTokenAddress, l1Signer).approve( - inboxAddress, - depositAmount - ) - ).wait() - - // bridge it - const orbitInboxAbi = [ - 'function depositERC20(uint256) public returns (uint256)', - ] - const orbitInbox = new Contract(inboxAddress, orbitInboxAbi, l1Signer) - await (await orbitInbox.depositERC20(depositAmount)).wait() - await sleep(30 * 1000) -} - -async function deployContractBehindProxy< - T extends ContractFactory, - U extends Contract ->( - deployer: Signer, - logicFactory: new (deployer: Signer) => T, - proxyAdmin: string, - contractFactory: (address: string, signer: Signer) => U -): Promise { - const logicContract = await new logicFactory(deployer).deploy() - await logicContract.deployed() - - const proxyContract = await new TransparentUpgradeableProxy__factory( - deployer - ).deploy(logicContract.address, proxyAdmin, '0x') - await proxyContract.deployed() - - return contractFactory(proxyContract.address, deployer) -} - -async function main() { - const config = { - arbUrl: 'http://localhost:8547', - ethUrl: 'http://localhost:8545', - } - - const l1Provider = new ethers.providers.JsonRpcProvider(config.ethUrl) - const l2Provider = new ethers.providers.JsonRpcProvider(config.arbUrl) - - const l1DeployerWallet = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - l1Provider - ) - const l2DeployerWallet = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - l2Provider - ) - - const { l1Network, l2Network } = await setupOrbitTokenBridge( - l1DeployerWallet, - l2DeployerWallet, - config.ethUrl, - config.arbUrl - ) - - const NETWORK_FILE = 'network.json' - fs.writeFileSync( - NETWORK_FILE, - JSON.stringify({ l1Network, l2Network }, null, 2) - ) - console.log(NETWORK_FILE + ' updated') -} - -main().then(() => console.log('Done.')) diff --git a/scripts/local-deployment/tokenBridgeDeployer.ts b/scripts/local-deployment/tokenBridgeDeployer.ts deleted file mode 100644 index b52a465b59..0000000000 --- a/scripts/local-deployment/tokenBridgeDeployer.ts +++ /dev/null @@ -1,392 +0,0 @@ -import { - Contract, - ContractFactory, - Signer, - Wallet, - constants, - ethers, -} from 'ethers' -import { - BeaconProxyFactory__factory, - L1CustomGateway__factory, - L1ERC20Gateway__factory, - L1GatewayRouter__factory, - L2CustomGateway__factory, - L2ERC20Gateway__factory, - L2GatewayRouter__factory, - ProxyAdmin__factory, - StandardArbERC20__factory, - TransparentUpgradeableProxy__factory, - UpgradeableBeacon__factory, -} from '../../build/types' -import { JsonRpcProvider } from '@ethersproject/providers' -import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' -import { execSync } from 'child_process' -import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' -import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' -import * as fs from 'fs' - -export const setupTokenBridge = async ( - l1Deployer: Signer, - l2Deployer: Signer, - l1Url: string, - l2Url: string -) => { - const { l1Network, l2Network: coreL2Network } = await getLocalNetworks( - l1Url, - l2Url - ) - - const { l1: l1Contracts, l2: l2Contracts } = await deployTokenBridgeAndInit( - l1Deployer, - l2Deployer, - coreL2Network.ethBridge.inbox - ) - const l2Network: L2Network = { - ...coreL2Network, - tokenBridge: { - l1CustomGateway: l1Contracts.customGateway.address, - l1ERC20Gateway: l1Contracts.standardGateway.address, - l1GatewayRouter: l1Contracts.router.address, - l1MultiCall: '', - l1ProxyAdmin: l1Contracts.proxyAdmin.address, - l1Weth: '', - l1WethGateway: '', - - l2CustomGateway: l2Contracts.customGateway.address, - l2ERC20Gateway: l2Contracts.standardGateway.address, - l2GatewayRouter: l2Contracts.router.address, - l2Multicall: '', - l2ProxyAdmin: l2Contracts.proxyAdmin.address, - l2Weth: '', - l2WethGateway: '', - }, - } - - addCustomNetwork({ - customL1Network: l1Network, - customL2Network: l2Network, - }) - - return { - l1Network, - l2Network, - } -} - -/** - * Deploy all the L1 and L2 contracts and do the initialization. - * - * @param l1Signer - * @param l2Signer - * @param inboxAddress - * @returns - */ -export const deployTokenBridgeAndInit = async ( - l1Signer: Signer, - l2Signer: Signer, - inboxAddress: string -) => { - console.log('deploying l1 side') - const l1 = await deployTokenBridgeL1Side(l1Signer) - - // fund L2 deployer so contracts can be deployed - await bridgeFundsToL2Deployer(l1Signer, inboxAddress) - - console.log('deploying l2 side') - const l2 = await deployTokenBridgeL2Side(l2Signer) - - console.log('initialising L2') - await l2.router.initialize(l1.router.address, l2.standardGateway.address) - await l2.beaconProxyFactory.initialize(l2.beacon.address) - await ( - await l2.standardGateway.initialize( - l1.standardGateway.address, - l2.router.address, - l2.beaconProxyFactory.address - ) - ).wait() - await ( - await l2.customGateway.initialize( - l1.customGateway.address, - l2.router.address - ) - ).wait() - - console.log('initialising L1') - await ( - await l1.router.initialize( - await l1Signer.getAddress(), - l1.standardGateway.address, - constants.AddressZero, - l2.router.address, - inboxAddress - ) - ).wait() - - await ( - await l1.standardGateway.initialize( - l2.standardGateway.address, - l1.router.address, - inboxAddress, - await l2.beaconProxyFactory.cloneableProxyHash(), - l2.beaconProxyFactory.address - ) - ).wait() - await ( - await l1.customGateway.initialize( - l2.customGateway.address, - l1.router.address, - inboxAddress, - await l1Signer.getAddress() - ) - ).wait() - - return { l1, l2 } -} - -const deployTokenBridgeL1Side = async (deployer: Signer) => { - const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() - await proxyAdmin.deployed() - console.log('proxyAdmin', proxyAdmin.address) - - const router = await deployContractBehindProxy( - deployer, - L1GatewayRouter__factory, - proxyAdmin.address, - L1GatewayRouter__factory.connect - ) - console.log('router', router.address) - - const standardGateway = await deployContractBehindProxy( - deployer, - L1ERC20Gateway__factory, - proxyAdmin.address, - L1ERC20Gateway__factory.connect - ) - console.log('standardGateway', standardGateway.address) - - const customGateway = await deployContractBehindProxy( - deployer, - L1CustomGateway__factory, - proxyAdmin.address, - L1CustomGateway__factory.connect - ) - console.log('customGateway', standardGateway.address) - - return { - proxyAdmin, - router, - standardGateway, - customGateway, - } -} - -const deployTokenBridgeL2Side = async (deployer: Signer) => { - const proxyAdmin = await new ProxyAdmin__factory(deployer).deploy() - await proxyAdmin.deployed() - - const router = await deployContractBehindProxy( - deployer, - L2GatewayRouter__factory, - proxyAdmin.address, - L2GatewayRouter__factory.connect - ) - - const standardGateway = await deployContractBehindProxy( - deployer, - L2ERC20Gateway__factory, - proxyAdmin.address, - L2ERC20Gateway__factory.connect - ) - - const customGateway = await deployContractBehindProxy( - deployer, - L2CustomGateway__factory, - proxyAdmin.address, - L2CustomGateway__factory.connect - ) - - const standardArbERC20 = await new StandardArbERC20__factory( - deployer - ).deploy() - await standardArbERC20.deployed() - - const beacon = await new UpgradeableBeacon__factory(deployer).deploy( - standardArbERC20.address - ) - await beacon.deployed() - - const beaconProxyFactory = await new BeaconProxyFactory__factory( - deployer - ).deploy() - await beaconProxyFactory.deployed() - - return { - proxyAdmin, - router, - standardGateway, - customGateway, - standardArbERC20, - beacon, - beaconProxyFactory, - } -} - -const bridgeFundsToL2Deployer = async ( - l1Signer: Signer, - inboxAddress: string -) => { - console.log('fund L2 deployer') - - const depositAmount = ethers.utils.parseUnits('3', 'ether') - - // bridge it - const InboxAbi = ['function depositEth() public payable returns (uint256)'] - const Inbox = new Contract(inboxAddress, InboxAbi, l1Signer) - await (await Inbox.depositEth({ value: depositAmount })).wait() - await sleep(30 * 1000) -} - -async function deployContractBehindProxy< - T extends ContractFactory, - U extends Contract ->( - deployer: Signer, - logicFactory: new (deployer: Signer) => T, - proxyAdmin: string, - contractFactory: (address: string, signer: Signer) => U -): Promise { - const logicContract = await new logicFactory(deployer).deploy() - await logicContract.deployed() - - const proxyContract = await new TransparentUpgradeableProxy__factory( - deployer - ).deploy(logicContract.address, proxyAdmin, '0x') - await proxyContract.deployed() - - return contractFactory(proxyContract.address, deployer) -} - -export const getLocalNetworks = async ( - l1Url: string, - l2Url: string -): Promise<{ - l1Network: L1Network - l2Network: Omit -}> => { - const l1Provider = new JsonRpcProvider(l1Url) - const l2Provider = new JsonRpcProvider(l2Url) - let deploymentData: string - try { - deploymentData = execSync( - 'docker exec nitro_testnode_sequencer_1 cat /config/deployment.json' - ).toString() - } catch (e) { - deploymentData = execSync( - 'docker exec nitro-testnode-sequencer-1 cat /config/deployment.json' - ).toString() - } - const parsedDeploymentData = JSON.parse(deploymentData) as { - bridge: string - inbox: string - ['sequencer-inbox']: string - rollup: string - } - - const rollup = RollupAdminLogic__factory.connect( - parsedDeploymentData.rollup, - l1Provider - ) - const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() - - const bridge = Bridge__factory.connect( - parsedDeploymentData.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 = { - chainID: l2NetworkInfo.chainId, - confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), - ethBridge: { - bridge: parsedDeploymentData.bridge, - inbox: parsedDeploymentData.inbox, - outbox: outboxAddr, - rollup: parsedDeploymentData.rollup, - sequencerInbox: parsedDeploymentData['sequencer-inbox'], - }, - explorerUrl: '', - isArbitrum: true, - isCustom: true, - name: 'ArbLocal', - partnerChainID: l1NetworkInfo.chainId, - retryableLifetimeSeconds: 7 * 24 * 60 * 60, - nitroGenesisBlock: 0, - nitroGenesisL1Block: 0, - depositTimeout: 900000, - } - return { - l1Network, - l2Network, - } -} - -export const getSigner = (provider: JsonRpcProvider, key?: string) => { - if (!key && !provider) - throw new Error('Provide at least one of key or provider.') - if (key) return new Wallet(key).connect(provider) - else return provider.getSigner(0) -} - -export function sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)) -} - -async function main() { - const config = { - arbUrl: 'http://localhost:8547', - ethUrl: 'http://localhost:8545', - } - - const l1Provider = new ethers.providers.JsonRpcProvider(config.ethUrl) - const l2Provider = new ethers.providers.JsonRpcProvider(config.arbUrl) - - const l1DeployerWallet = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - l1Provider - ) - const l2DeployerWallet = new ethers.Wallet( - ethers.utils.sha256(ethers.utils.toUtf8Bytes('user_l1user')), - l2Provider - ) - - const { l1Network, l2Network } = await setupTokenBridge( - l1DeployerWallet, - l2DeployerWallet, - config.ethUrl, - config.arbUrl - ) - - const NETWORK_FILE = 'network.json' - fs.writeFileSync( - NETWORK_FILE, - JSON.stringify({ l1Network, l2Network }, null, 2) - ) - console.log(NETWORK_FILE + ' updated') -} - -main().then(() => console.log('Done.')) From 79bf2675b42431e4aa375c4c460754c87df72034 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 4 Aug 2023 09:21:26 +0200 Subject: [PATCH 136/163] Use existing proxy admin --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index ee4ff42f4d..baebb61e77 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -48,6 +48,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { error L1AtomicTokenBridgeCreator_OnlyRollupOwner(); error L1AtomicTokenBridgeCreator_InvalidRouterAddr(); error L1AtomicTokenBridgeCreator_TemplatesNotSet(); + error L1AtomicTokenBridgeCreator_ProxyAdminNotFound(); event OrbitTokenBridgeCreated( address indexed inbox, @@ -242,8 +243,11 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address wethGateway ) { - address proxyAdmin = - address(new ProxyAdmin{ salt: _getL1Salt(OrbitSalts.L1_PROXY_ADMIN, inbox) }()); + // fetch existing proxy admin from inbox + address proxyAdmin = IInbox_ProxyAdmin(inbox).getProxyAdmin(); + if (proxyAdmin == address(0)) { + revert L1AtomicTokenBridgeCreator_ProxyAdminNotFound(); + } // deploy router address routerTemplate = isUsingFeeToken @@ -645,3 +649,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { interface IERC20Bridge { function nativeToken() external view returns (address); } + +interface IInbox_ProxyAdmin { + function getProxyAdmin() external view returns (address); +} From b0edcfd51ee65b23e8965260216905ea814442dd Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 4 Aug 2023 14:43:50 +0200 Subject: [PATCH 137/163] Do not use IEthInbox interface --- .../ethereum/L1ArbitrumMessenger.sol | 17 ++--------------- lib/nitro-contracts | 2 +- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol b/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol index 2f8d50475f..f433a706a7 100644 --- a/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol +++ b/contracts/tokenbridge/ethereum/L1ArbitrumMessenger.sol @@ -176,7 +176,7 @@ abstract contract L1ArbitrumMessenger { bytes memory _data ) internal virtual returns (uint256) { return - IEthInbox(_inbox).createRetryableTicket{ value: _totalFeeAmount }( + IInbox(_inbox).createRetryableTicket{ value: _totalFeeAmount }( _to, _l2CallValue, _maxSubmissionCost, @@ -201,17 +201,4 @@ interface IERC20Inbox { uint256 tokenTotalFeeAmount, bytes calldata data ) external returns (uint256); -} - -interface IEthInbox { - function createRetryableTicket( - address to, - uint256 l2CallValue, - uint256 maxSubmissionCost, - address excessFeeRefundAddress, - address callValueRefundAddress, - uint256 gasLimit, - uint256 maxFeePerGas, - bytes calldata data - ) external payable returns (uint256); -} +} \ No newline at end of file diff --git a/lib/nitro-contracts b/lib/nitro-contracts index f8fad6fd6a..a182f842f1 160000 --- a/lib/nitro-contracts +++ b/lib/nitro-contracts @@ -1 +1 @@ -Subproject commit f8fad6fd6a79a45a1a6c8aa3629fd9b82522fa1d +Subproject commit a182f842f13f437040dcadfcb6741f20ea929272 From cd35fef09dca6d20f6c88b42a502d84e44a86c55 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Sun, 6 Aug 2023 13:03:51 +0200 Subject: [PATCH 138/163] Deploy UpgradeExecutor to L2 --- .gitignore | 2 + .../arbitrum/L2AtomicTokenBridgeFactory.sol | 46 +++++++++- .../ethereum/L1AtomicTokenBridgeCreator.sol | 84 +++++++++++-------- .../ethereum/L1TokenBridgeRetryableSender.sol | 19 +++-- .../tokenbridge/libraries/UpgradeExecutor.sol | 57 +++++++++++++ scripts/atomicTokenBridgeDeployer.ts | 7 ++ 6 files changed, 171 insertions(+), 44 deletions(-) create mode 100644 contracts/tokenbridge/libraries/UpgradeExecutor.sol diff --git a/.gitignore b/.gitignore index 7974e8b46c..ae5e00a019 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ +.gitignore .env node_modules +.vscode/ #Hardhat files cache diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 51bdd941fd..84e03f4978 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -6,6 +6,7 @@ import {L2ERC20Gateway} from "./gateway/L2ERC20Gateway.sol"; import {L2CustomGateway} from "./gateway/L2CustomGateway.sol"; import {L2WethGateway} from "./gateway/L2WethGateway.sol"; import {StandardArbERC20} from "./StandardArbERC20.sol"; +import {UpgradeExecutor} from "../libraries/UpgradeExecutor.sol"; import {BeaconProxyFactory} from "../libraries/ClonableBeaconProxy.sol"; import {aeWETH} from "../libraries/aeWETH.sol"; import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; @@ -30,7 +31,8 @@ contract L2AtomicTokenBridgeFactory { address l1WethGateway, address l1Weth, address l2StandardGatewayCanonicalAddress, - address rollupOwner + address rollupOwner, + address aliasedL1UpgradeExecutor ) external { // create proxyAdmin which will be used for all contracts address proxyAdmin = @@ -41,6 +43,9 @@ contract L2AtomicTokenBridgeFactory { _deployRouter(l2Code.router, l1Router, l2StandardGatewayCanonicalAddress, proxyAdmin); _deployStandardGateway(l2Code.standardGateway, l1StandardGateway, router, proxyAdmin); _deployCustomGateway(l2Code.customGateway, l1CustomGateway, router, proxyAdmin); + address upgradeExecutor = _deployUpgradeExecutor( + l2Code.upgradeExecutor, rollupOwner, proxyAdmin, aliasedL1UpgradeExecutor + ); // fee token based creator will provide address(0) as WETH is not used in ERC20-based chains if (l1WethGateway != address(0)) { @@ -49,8 +54,40 @@ contract L2AtomicTokenBridgeFactory { ); } - // transfer ownership to rollup's owner - ProxyAdmin(proxyAdmin).transferOwnership(rollupOwner); + // transfer ownership to L2 upgradeExecutor + ProxyAdmin(proxyAdmin).transferOwnership(upgradeExecutor); + } + + function _deployUpgradeExecutor( + bytes calldata runtimeCode, + address rollupOwner, + address proxyAdmin, + address aliasedL1UpgradeExecutor + ) internal returns (address) { + // canonical L2 upgrade executor with dummy logic + address canonicalUpgradeExecutor = address( + new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_EXECUTOR) }( + address(new CanonicalAddressSeed{ salt: _getL2Salt(OrbitSalts.L2_EXECUTOR_LOGIC) }()), + proxyAdmin, + bytes("") + ) + ); + + // create UpgradeExecutor logic and upgrade to it + address upExecutorLogic = Create2.deploy( + 0, _getL2Salt(OrbitSalts.L2_EXECUTOR_LOGIC), _creationCodeFor(runtimeCode) + ); + ProxyAdmin(proxyAdmin).upgrade( + ITransparentUpgradeableProxy(canonicalUpgradeExecutor), upExecutorLogic + ); + + // init upgrade executor + address[] memory executors = new address[](2); + executors[0] = rollupOwner; + executors[1] = aliasedL1UpgradeExecutor; + UpgradeExecutor(canonicalUpgradeExecutor).initialize(canonicalUpgradeExecutor, executors); + + return canonicalUpgradeExecutor; } function _deployRouter( @@ -250,6 +287,7 @@ struct L2RuntimeCode { bytes customGateway; bytes wethGateway; bytes aeWeth; + bytes upgradeExecutor; } /** @@ -277,4 +315,6 @@ library OrbitSalts { bytes32 public constant L2_STANDARD_ERC20 = keccak256(bytes("OrbitStandardArbERC20")); bytes32 public constant UPGRADEABLE_BEACON = keccak256(bytes("OrbitUpgradeableBeacon")); bytes32 public constant BEACON_PROXY_FACTORY = keccak256(bytes("OrbitBeaconProxyFactory")); + bytes32 public constant L2_EXECUTOR_LOGIC = keccak256(bytes("OrbitL2UpgradeExecutorLogic")); + bytes32 public constant L2_EXECUTOR = keccak256(bytes("OrbitL2UpgradeExecutorProxy")); } diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index baebb61e77..27b660544f 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -28,6 +28,8 @@ import { ProxyAdmin } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import {BytesLib} from "../libraries/BytesLib.sol"; +import {UpgradeExecutor} from "../libraries/UpgradeExecutor.sol"; +import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; @@ -70,6 +72,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { L1OrbitGatewayRouter feeTokenBasedRouterTemplate; L1OrbitERC20Gateway feeTokenBasedStandardGatewayTemplate; L1OrbitCustomGateway feeTokenBasedCustomGatewayTemplate; + UpgradeExecutor upgradeExecutor; } // non-canonical router registry @@ -180,30 +183,37 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } bool isUsingFeeToken = _getFeeToken(inbox) != address(0); + address rollupOwner = _getRollupOwner(inbox); - // deploy L1 side of token bridge - address owner = _getRollupOwner(inbox); - (address router, address standardGateway, address customGateway, address wethGateway) = - _deployL1Contracts(inbox, owner, isUsingFeeToken); + /// deploy L1 side of token bridge + ( + address router, + address standardGateway, + address customGateway, + address wethGateway, + address proxyAdmin + ) = _deployL1Contracts(inbox, rollupOwner, isUsingFeeToken); /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls if (isUsingFeeToken) { _deployL2Factory(inbox, gasPriceBid, isUsingFeeToken); _deployL2ContractsUsingFeeToken( - router, standardGateway, customGateway, inbox, maxGasForContracts, gasPriceBid + L1Addresses(router, standardGateway, customGateway, address(0), address(0)), + inbox, + maxGasForContracts, + gasPriceBid, + proxyAdmin ); } else { uint256 valueSpentForFactory = _deployL2Factory(inbox, gasPriceBid, isUsingFeeToken); uint256 fundsRemaining = msg.value - valueSpentForFactory; _deployL2ContractsUsingEth( - router, - standardGateway, - customGateway, - wethGateway, + L1Addresses(router, standardGateway, customGateway, wethGateway, l1Weth), inbox, maxGasForContracts, gasPriceBid, - fundsRemaining + fundsRemaining, + proxyAdmin ); } } @@ -234,17 +244,18 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return getCanonicalL1RouterAddress(inbox); } - function _deployL1Contracts(address inbox, address owner, bool isUsingFeeToken) + function _deployL1Contracts(address inbox, address rollupOwner, bool isUsingFeeToken) internal returns ( address router, address standardGateway, address customGateway, - address wethGateway + address wethGateway, + address proxyAdmin ) { - // fetch existing proxy admin from inbox - address proxyAdmin = IInbox_ProxyAdmin(inbox).getProxyAdmin(); + // get existing proxy admin + proxyAdmin = IInbox_ProxyAdmin(inbox).getProxyAdmin(); if (proxyAdmin == address(0)) { revert L1AtomicTokenBridgeCreator_ProxyAdminNotFound(); } @@ -263,20 +274,18 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // deploy and init gateways standardGateway = _deployL1StandardGateway(proxyAdmin, router, inbox, isUsingFeeToken); - customGateway = _deployL1CustomGateway(proxyAdmin, router, inbox, owner, isUsingFeeToken); + customGateway = + _deployL1CustomGateway(proxyAdmin, router, inbox, rollupOwner, isUsingFeeToken); wethGateway = isUsingFeeToken ? address(0) : _deployL1WethGateway(proxyAdmin, router, inbox); // init router L1GatewayRouter(router).initialize( - owner, address(standardGateway), address(0), getCanonicalL2RouterAddress(), inbox + rollupOwner, address(standardGateway), address(0), getCanonicalL2RouterAddress(), inbox ); - // transfer ownership to owner - ProxyAdmin(proxyAdmin).transferOwnership(owner); - // emit it emit OrbitTokenBridgeCreated( - inbox, owner, router, standardGateway, customGateway, wethGateway, proxyAdmin + inbox, rollupOwner, router, standardGateway, customGateway, wethGateway, proxyAdmin ); } @@ -399,15 +408,15 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function _deployL2ContractsUsingEth( - address l1Router, - address l1StandardGateway, - address l1CustomGateway, - address l1WethGateway, + L1Addresses memory l1Addresses, address inbox, uint256 maxGas, uint256 gasPriceBid, - uint256 availableFunds + uint256 availableFunds, + address proxyAdmin ) internal { + address upgradeExecutor = ProxyAdmin(proxyAdmin).owner(); + retryableSender.sendRetryableUsingEth{value: availableFunds}( RetryableParams( inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxGas, gasPriceBid @@ -417,23 +426,26 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { l2StandardGatewayTemplate, l2CustomGatewayTemplate, l2WethGatewayTemplate, - l2WethTemplate + l2WethTemplate, + address(l1Templates.upgradeExecutor) ), - L1Addresses(l1Router, l1StandardGateway, l1CustomGateway, l1WethGateway, l1Weth), + l1Addresses, getCanonicalL2StandardGatewayAddress(), _getRollupOwner(inbox), - msg.sender + msg.sender, + AddressAliasHelper.applyL1ToL2Alias(upgradeExecutor) ); } function _deployL2ContractsUsingFeeToken( - address l1Router, - address l1StandardGateway, - address l1CustomGateway, + L1Addresses memory l1Addresses, address inbox, uint256 maxGas, - uint256 gasPriceBid + uint256 gasPriceBid, + address proxyAdmin ) internal { + address upgradeExecutor = ProxyAdmin(proxyAdmin).owner(); + // transfer fee tokens to inbox to pay for 2nd retryable address feeToken = _getFeeToken(inbox); uint256 fee = maxGas * gasPriceBid; @@ -448,11 +460,13 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { l2StandardGatewayTemplate, l2CustomGatewayTemplate, address(0), - address(0) + address(0), + address(l1Templates.upgradeExecutor) ), - L1Addresses(l1Router, l1StandardGateway, l1CustomGateway, address(0), address(0)), + l1Addresses, getCanonicalL2StandardGatewayAddress(), - _getRollupOwner(inbox) + _getRollupOwner(inbox), + AddressAliasHelper.applyL1ToL2Alias(upgradeExecutor) ); } diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index 94d42ae6f3..72b9af1f1b 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -45,7 +45,8 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { L1Addresses calldata l1, address l2StandardGatewayAddress, address rollupOwner, - address deployer + address deployer, + address aliasedL1UpgradeExecutor ) external payable onlyOwner { bytes memory data = abi.encodeCall( L2AtomicTokenBridgeFactory.deployL2Contracts, @@ -55,7 +56,8 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { l2.standardGatewayTemplate.code, l2.customGatewayTemplate.code, l2.wethGatewayTemplate.code, - l2.wethTemplate.code + l2.wethTemplate.code, + l2.upgradeExecutorTemplate.code ), l1.router, l1.standardGateway, @@ -63,7 +65,8 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { l1.wethGateway, l1.weth, l2StandardGatewayAddress, - rollupOwner + rollupOwner, + aliasedL1UpgradeExecutor ) ); @@ -89,7 +92,8 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { L2TemplateAddresses calldata l2, L1Addresses calldata l1, address l2StandardGatewayAddress, - address rollupOwner + address rollupOwner, + address aliasedL1UpgradeExecutor ) external payable onlyOwner { bytes memory data = abi.encodeCall( L2AtomicTokenBridgeFactory.deployL2Contracts, @@ -99,7 +103,8 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { l2.standardGatewayTemplate.code, l2.customGatewayTemplate.code, "", - "" + "", + l2.upgradeExecutorTemplate.code ), l1.router, l1.standardGateway, @@ -107,7 +112,8 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { address(0), address(0), l2StandardGatewayAddress, - rollupOwner + rollupOwner, + aliasedL1UpgradeExecutor ) ); @@ -174,6 +180,7 @@ struct L2TemplateAddresses { address customGatewayTemplate; address wethGatewayTemplate; address wethTemplate; + address upgradeExecutorTemplate; } /** diff --git a/contracts/tokenbridge/libraries/UpgradeExecutor.sol b/contracts/tokenbridge/libraries/UpgradeExecutor.sol new file mode 100644 index 0000000000..ada8c6ded1 --- /dev/null +++ b/contracts/tokenbridge/libraries/UpgradeExecutor.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.4; + +import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; +import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; + +/// @title A root contract from which it execute upgrades +/// @notice Does not contain upgrade logic itself, only the means to call upgrade contracts and execute them +/// @dev We use these upgrade contracts as they allow multiple actions to take place in an upgrade +/// and for these actions to interact. However because we are delegatecalling into these upgrade +/// contracts, it's important that these upgrade contract do not touch or modify contract state. +contract UpgradeExecutor is Initializable, AccessControlUpgradeable, ReentrancyGuard { + using Address for address; + + bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); + bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); + + /// @notice Emitted when an upgrade execution occurs + event UpgradeExecuted(address indexed upgrade, uint256 value, bytes data); + + /// @notice Initialise the upgrade executor + /// @param admin The admin who can update other roles, and itself - ADMIN_ROLE + /// @param executors Can call the execute function - EXECUTOR_ROLE + function initialize(address admin, address[] memory executors) public initializer { + require(admin != address(0), "UpgradeExecutor: zero admin"); + + __AccessControl_init(); + + _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE); + _setRoleAdmin(EXECUTOR_ROLE, ADMIN_ROLE); + + _setupRole(ADMIN_ROLE, admin); + for (uint256 i = 0; i < executors.length; ++i) { + _setupRole(EXECUTOR_ROLE, executors[i]); + } + } + + /// @notice Execute an upgrade by delegate calling an upgrade contract + /// @dev Only executor can call this. Since we're using a delegatecall here the Upgrade contract + /// will have access to the state of this contract - including the roles. Only upgrade contracts + /// that do not touch local state should be used. + function execute(address upgrade, bytes memory upgradeCallData) + public + payable + onlyRole(EXECUTOR_ROLE) + nonReentrant + { + // OZ Address library check if the address is a contract and bubble up inner revert reason + address(upgrade).functionDelegateCall( + upgradeCallData, + "UpgradeExecutor: inner delegate call failed without reason" + ); + + emit UpgradeExecuted(upgrade, msg.value, upgradeCallData); + } +} diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index ed0dc31fec..68e1228232 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -21,6 +21,7 @@ import { IInbox__factory, IERC20Bridge__factory, IERC20__factory, + UpgradeExecutor__factory, } from '../build/types' import { JsonRpcProvider } from '@ethersproject/providers' import { @@ -301,6 +302,11 @@ export const deployL1TokenBridgeCreator = async ( await new L1OrbitCustomGateway__factory(l1Deployer).deploy() await feeTokenBasedCustomGatewayTemplate.deployed() + const upgradeExecutor = await new UpgradeExecutor__factory( + l1Deployer + ).deploy() + await upgradeExecutor.deployed() + const l1Templates = { routerTemplate: routerTemplate.address, standardGatewayTemplate: standardGatewayTemplate.address, @@ -311,6 +317,7 @@ export const deployL1TokenBridgeCreator = async ( feeTokenBasedStandardGatewayTemplate.address, feeTokenBasedCustomGatewayTemplate: feeTokenBasedCustomGatewayTemplate.address, + upgradeExecutor: upgradeExecutor, } /// deploy L2 contracts as placeholders on L1 From ab468c15c60d80d86b28941fdecfebd273b3d3d4 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Sun, 6 Aug 2023 22:34:06 +0200 Subject: [PATCH 139/163] Refactor upgrade executor flow --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 18 +++++--- .../ethereum/L1AtomicTokenBridgeCreator.sol | 42 ++++++++++++++++--- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 84e03f4978..ae817ec81e 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -38,14 +38,16 @@ contract L2AtomicTokenBridgeFactory { address proxyAdmin = address(new ProxyAdmin{ salt: _getL2Salt(OrbitSalts.L2_PROXY_ADMIN) }()); - // deploy router/gateways - address router = - _deployRouter(l2Code.router, l1Router, l2StandardGatewayCanonicalAddress, proxyAdmin); - _deployStandardGateway(l2Code.standardGateway, l1StandardGateway, router, proxyAdmin); - _deployCustomGateway(l2Code.customGateway, l1CustomGateway, router, proxyAdmin); + // deploy router/gateways/executor address upgradeExecutor = _deployUpgradeExecutor( l2Code.upgradeExecutor, rollupOwner, proxyAdmin, aliasedL1UpgradeExecutor ); + address router = + _deployRouter(l2Code.router, l1Router, l2StandardGatewayCanonicalAddress, proxyAdmin); + _deployStandardGateway( + l2Code.standardGateway, l1StandardGateway, router, proxyAdmin, upgradeExecutor + ); + _deployCustomGateway(l2Code.customGateway, l1CustomGateway, router, proxyAdmin); // fee token based creator will provide address(0) as WETH is not used in ERC20-based chains if (l1WethGateway != address(0)) { @@ -120,7 +122,8 @@ contract L2AtomicTokenBridgeFactory { bytes calldata runtimeCode, address l1StandardGateway, address router, - address proxyAdmin + address proxyAdmin, + address upgradeExecutor ) internal { // canonical L2 standard gateway with dummy logic address canonicalStdGateway = address( @@ -159,6 +162,9 @@ contract L2AtomicTokenBridgeFactory { L2ERC20Gateway(canonicalStdGateway).initialize( l1StandardGateway, router, address(beaconProxyFactory) ); + + // make L2 executor the beacon owner + beacon.transferOwnership(upgradeExecutor); } function _deployCustomGateway( diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 27b660544f..cbb4b71744 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -59,7 +59,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address standardGateway, address customGateway, address wethGateway, - address proxyAdmin + address proxyAdmin, + address upgradeExecutor ); event OrbitTokenBridgeTemplatesUpdated(); event NonCanonicalRouterSet(address indexed inbox, address indexed router); @@ -254,11 +255,12 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address proxyAdmin ) { - // get existing proxy admin + // get existing proxy admin and upgrade executor proxyAdmin = IInbox_ProxyAdmin(inbox).getProxyAdmin(); if (proxyAdmin == address(0)) { revert L1AtomicTokenBridgeCreator_ProxyAdminNotFound(); } + address upgradeExecutor = ProxyAdmin(proxyAdmin).owner(); // deploy router address routerTemplate = isUsingFeeToken @@ -275,17 +277,28 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // deploy and init gateways standardGateway = _deployL1StandardGateway(proxyAdmin, router, inbox, isUsingFeeToken); customGateway = - _deployL1CustomGateway(proxyAdmin, router, inbox, rollupOwner, isUsingFeeToken); + _deployL1CustomGateway(proxyAdmin, router, inbox, upgradeExecutor, isUsingFeeToken); wethGateway = isUsingFeeToken ? address(0) : _deployL1WethGateway(proxyAdmin, router, inbox); // init router L1GatewayRouter(router).initialize( - rollupOwner, address(standardGateway), address(0), getCanonicalL2RouterAddress(), inbox + upgradeExecutor, + address(standardGateway), + address(0), + getCanonicalL2RouterAddress(), + inbox ); // emit it emit OrbitTokenBridgeCreated( - inbox, rollupOwner, router, standardGateway, customGateway, wethGateway, proxyAdmin + inbox, + rollupOwner, + router, + standardGateway, + customGateway, + wethGateway, + proxyAdmin, + upgradeExecutor ); } @@ -589,6 +602,25 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); } + function getCanonicalL2UpgradeExecutorAddress() public view returns (address) { + address logicSeedAddress = Create2.computeAddress( + _getL2Salt(OrbitSalts.L2_EXECUTOR_LOGIC), + keccak256(type(CanonicalAddressSeed).creationCode), + canonicalL2FactoryAddress + ); + + return Create2.computeAddress( + _getL2Salt(OrbitSalts.L2_EXECUTOR), + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) + ) + ), + canonicalL2FactoryAddress + ); + } + function _getFeeToken(address inbox) internal view returns (address) { address bridge = address(IInbox(inbox).bridge()); From 18ec4b652a33c425c8621d05823397e48ee28eec Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Sun, 6 Aug 2023 22:35:06 +0200 Subject: [PATCH 140/163] Rename env vars --- .env-sample | 15 +++++++++++---- scripts/atomicTokenBridgeDeployer.ts | 4 +++- scripts/goerli-deployment/createTokenBridge.ts | 8 ++++---- .../goerli-deployment/deployTokenBridgeCreator.ts | 8 ++++---- .../deployCreatorAndCreateTokenBridge.ts | 6 ++++-- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/.env-sample b/.env-sample index 9e3413c0b9..a496dd2487 100644 --- a/.env-sample +++ b/.env-sample @@ -1,4 +1,11 @@ -## Goerli - Deploy L1TokenBridgeCreator -ARB_GOERLI_RPC="" -ARB_GOERLI_DEPLOYER_KEY="" -ORBIT_RPC="" \ No newline at end of file +.env-sample +## RPC endpoints +BASECHAIN_RPC="" +ORBIT_RPC="" + +## Deployer key used for deploying creator and creating token bridge +BASECHAIN_DEPLOYER_KEY="" + +## Optional args, used for verification script. If not provided info is read from network.json +ROLLUP_ADDRESS="" +L1_TOKEN_BRIDGE_CREATOR="" diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index 68e1228232..b062dc3f98 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -75,6 +75,7 @@ export const createTokenBridge = async ( customGateway: L2CustomGateway__factory.bytecode, wethGateway: L2WethGateway__factory.bytecode, aeWeth: AeWETH__factory.bytecode, + upgradeExecutor: UpgradeExecutor__factory.bytecode, } const gasEstimateToDeployContracts = await l2FactoryTemplate.estimateGas.deployL2Contracts( @@ -85,6 +86,7 @@ export const createTokenBridge = async ( ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address, + ethers.Wallet.createRandom().address, ethers.Wallet.createRandom().address ) const maxGasForContracts = gasEstimateToDeployContracts.mul(2) @@ -317,7 +319,7 @@ export const deployL1TokenBridgeCreator = async ( feeTokenBasedStandardGatewayTemplate.address, feeTokenBasedCustomGatewayTemplate: feeTokenBasedCustomGatewayTemplate.address, - upgradeExecutor: upgradeExecutor, + upgradeExecutor: upgradeExecutor.address, } /// deploy L2 contracts as placeholders on L1 diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts index 830cea8f88..88d0b0f352 100644 --- a/scripts/goerli-deployment/createTokenBridge.ts +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -9,8 +9,8 @@ import * as fs from 'fs' dotenv.config() export const envVars = { - baseChainRpc: process.env['ARB_GOERLI_RPC'] as string, - baseChainDeployerKey: process.env['ARB_GOERLI_DEPLOYER_KEY'] as string, + baseChainRpc: process.env['BASECHAIN_RPC'] as string, + baseChainDeployerKey: process.env['BASECHAIN_DEPLOYER_KEY'] as string, childChainRpc: process.env['ORBIT_RPC'] as string, } @@ -31,9 +31,9 @@ const L1_TOKEN_BRIDGE_CREATOR = '0x4Ba3aC2a2fEf26eAA6d05D71B79fde08Cb3078a9' */ export const createTokenBridgeOnGoerli = async (rollupAddress: string) => { if (envVars.baseChainRpc == undefined) - throw new Error('Missing ARB_GOERLI_RPC in env vars') + throw new Error('Missing BASECHAIN_RPC in env vars') if (envVars.baseChainDeployerKey == undefined) - throw new Error('Missing ARB_GOERLI_DEPLOYER_KEY in env vars') + throw new Error('Missing BASECHAIN_DEPLOYER_KEY in env vars') if (envVars.childChainRpc == undefined) throw new Error('Missing ORBIT_RPC in env vars') diff --git a/scripts/goerli-deployment/deployTokenBridgeCreator.ts b/scripts/goerli-deployment/deployTokenBridgeCreator.ts index 1c0498ba80..19048cbd0c 100644 --- a/scripts/goerli-deployment/deployTokenBridgeCreator.ts +++ b/scripts/goerli-deployment/deployTokenBridgeCreator.ts @@ -10,8 +10,8 @@ import dotenv from 'dotenv' dotenv.config() export const envVars = { - baseChainRpc: process.env['ARB_GOERLI_RPC'] as string, - baseChainDeployerKey: process.env['ARB_GOERLI_DEPLOYER_KEY'] as string, + baseChainRpc: process.env['BASECHAIN_RPC'] as string, + baseChainDeployerKey: process.env['BASECHAIN_DEPLOYER_KEY'] as string, childChainRpc: process.env['ORBIT_RPC'] as string, } @@ -32,9 +32,9 @@ const ARB_GOERLI_WETH = '0xEe01c0CD76354C383B8c7B4e65EA88D00B06f36f' */ export const deployTokenBridgeCreator = async (rollupAddress: string) => { if (envVars.baseChainRpc == undefined) - throw new Error('Missing ARB_GOERLI_RPC in env vars') + throw new Error('Missing BASECHAIN_RPC in env vars') if (envVars.baseChainDeployerKey == undefined) - throw new Error('Missing ARB_GOERLI_DEPLOYER_KEY in env vars') + throw new Error('Missing BASECHAIN_DEPLOYER_KEY in env vars') if (envVars.childChainRpc == undefined) throw new Error('Missing ORBIT_RPC in env vars') diff --git a/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts b/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts index 803fe30a9b..a312b0550c 100644 --- a/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts +++ b/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts @@ -109,6 +109,7 @@ export const setupTokenBridgeInLocalEnv = async () => { return { l1Network, l2Network, + l1TokenBridgeCreator, } } @@ -192,12 +193,13 @@ export const getLocalNetworks = async ( } async function main() { - const { l1Network, l2Network } = await setupTokenBridgeInLocalEnv() + const { l1Network, l2Network, l1TokenBridgeCreator } = + await setupTokenBridgeInLocalEnv() const NETWORK_FILE = 'network.json' fs.writeFileSync( NETWORK_FILE, - JSON.stringify({ l1Network, l2Network }, null, 2) + JSON.stringify({ l1Network, l2Network, l1TokenBridgeCreator }, null, 2) ) console.log(NETWORK_FILE + ' updated') } From 6f7ad280c4835eec5b5dee5839ae7e6fea4279d2 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Sun, 6 Aug 2023 22:35:27 +0200 Subject: [PATCH 141/163] Make verifivier script more complete --- test-e2e/tokenBridgeDeploymentTest.ts | 485 ++++++++++++++++---------- 1 file changed, 307 insertions(+), 178 deletions(-) diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index 395f68aa4f..4d18ad297b 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -1,11 +1,10 @@ -import { L1Network, L2Network, getL1Network, getL2Network } from '@arbitrum/sdk' -import { JsonRpcProvider } from '@ethersproject/providers' +import { JsonRpcProvider, Provider } from '@ethersproject/providers' import { BeaconProxyFactory__factory, IERC20Bridge__factory, IInbox__factory, - IOwnable, IOwnable__factory, + L1AtomicTokenBridgeCreator__factory, L1CustomGateway, L1CustomGateway__factory, L1ERC20Gateway, @@ -22,179 +21,159 @@ import { L2GatewayRouter__factory, L2WethGateway, L2WethGateway__factory, - ProxyAdmin, - ProxyAdmin__factory, + UpgradeExecutor, + UpgradeExecutor__factory, } from '../build/types' +import { RollupCore__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupCore__factory' +import { applyAlias } from '../test/testhelper' import path from 'path' import fs from 'fs' -import { - addCustomNetwork, - l1Networks, - l2Networks, -} from '@arbitrum/sdk/dist/lib/dataEntities/networks' import { expect } from 'chai' import { ethers } from 'hardhat' const config = { + l1Url: process.env.BASECHAIN_RPC || 'http://localhost:8545', l2Url: process.env.ORBIT_RPC || 'http://localhost:8547', - l1Url: process.env.ARB_GOERLI_RPC || 'http://localhost:8545', } -let _l1Network: L1Network -let _l2Network: L2Network - -let _l1Provider: JsonRpcProvider -let _l2Provider: JsonRpcProvider +let l1Provider: JsonRpcProvider +let l2Provider: JsonRpcProvider describe('tokenBridge', () => { it('should have deployed and initialized token bridge contracts', async function () { - const { l1Network, l1Provider, l2Network, l2Provider } = - await getProvidersAndSetupNetworks({ - l1Url: config.l1Url, - l2Url: config.l2Url, - networkFilename: './network.json', - }) + l1Provider = new JsonRpcProvider(config.l1Url) + l2Provider = new JsonRpcProvider(config.l2Url) + + /// get rollup and L1 creator addresses as entrypoint, either from env vars or from network.json + let rollupAddress: string + let l1TokenBridgeCreator: string + if (process.env.ROLLUP_ADDRESS && process.env.L1_TOKEN_BRIDGE_CREATOR) { + rollupAddress = process.env.ROLLUP_ADDRESS as string + l1TokenBridgeCreator = process.env.L1_TOKEN_BRIDGE_CREATOR as string + } else { + const localNetworkFile = path.join(__dirname, '..', 'network.json') + if (fs.existsSync(localNetworkFile)) { + const data = JSON.parse(fs.readFileSync(localNetworkFile).toString()) + rollupAddress = data['l2Network']['ethBridge']['rollup'] + l1TokenBridgeCreator = data['l1TokenBridgeCreator'] + } else { + throw new Error( + "Can't find rollup address info. Either set ROLLUP_ADDRESS env var or provide network.json file" + ) + } + } - _l1Network = l1Network - _l2Network = l2Network + /// get addresses + const { l1, l2 } = await _getTokenBridgeAddresses( + rollupAddress, + l1TokenBridgeCreator + ) - _l1Provider = l1Provider - _l2Provider = l2Provider + // console.log(l1) + // console.log('############') + // console.log(l2) + // exit() //// L1 checks await checkL1RouterInitialization( - L1GatewayRouter__factory.connect( - _l2Network.tokenBridge.l1GatewayRouter, - l1Provider - ) + L1GatewayRouter__factory.connect(l1.router, l1Provider), + l1.inbox, + l2 ) await checkL1StandardGatewayInitialization( - L1ERC20Gateway__factory.connect( - _l2Network.tokenBridge.l1ERC20Gateway, - l1Provider - ) + L1ERC20Gateway__factory.connect(l1.standardGateway, l1Provider), + l1, + l2 ) await checkL1CustomGatewayInitialization( - L1CustomGateway__factory.connect( - _l2Network.tokenBridge.l1CustomGateway, - l1Provider - ) + L1CustomGateway__factory.connect(l1.customGateway, l1Provider), + l1, + l2 ) - const usingFeeToken = await isUsingFeeToken( - _l2Network.ethBridge.inbox, - l1Provider - ) + const usingFeeToken = await isUsingFeeToken(l1.inbox, l1Provider) if (!usingFeeToken) await checkL1WethGatewayInitialization( - L1WethGateway__factory.connect( - _l2Network.tokenBridge.l1WethGateway, - l1Provider - ) + L1WethGateway__factory.connect(l1.wethGateway, l1Provider), + l1, + l2 ) //// L2 checks await checkL2RouterInitialization( - L2GatewayRouter__factory.connect( - _l2Network.tokenBridge.l2GatewayRouter, - l2Provider - ) + L2GatewayRouter__factory.connect(l2.router, l2Provider) ) await checkL2StandardGatewayInitialization( - L2ERC20Gateway__factory.connect( - _l2Network.tokenBridge.l2ERC20Gateway, - l2Provider - ) + L2ERC20Gateway__factory.connect(l2.standardGateway, l2Provider) ) await checkL2CustomGatewayInitialization( - L2CustomGateway__factory.connect( - _l2Network.tokenBridge.l2CustomGateway, - l2Provider - ) - ) - - const rollupOwner = await IOwnable__factory.connect( - _l2Network.ethBridge.rollup, - l1Provider - ).owner() - await checkOwnership( - rollupOwner.toLowerCase(), - ProxyAdmin__factory.connect( - _l2Network.tokenBridge.l1ProxyAdmin, - l1Provider - ), - ProxyAdmin__factory.connect( - _l2Network.tokenBridge.l2ProxyAdmin, - l2Provider - ), - L1GatewayRouter__factory.connect( - _l2Network.tokenBridge.l1GatewayRouter, - l1Provider - ), - L1CustomGateway__factory.connect( - _l2Network.tokenBridge.l1CustomGateway, - l1Provider - ) + L2CustomGateway__factory.connect(l2.customGateway, l2Provider) ) if (!usingFeeToken) { await checkL2WethGatewayInitialization( - L2WethGateway__factory.connect( - _l2Network.tokenBridge.l2WethGateway, - l2Provider - ) + L2WethGateway__factory.connect(l2.wethGateway, l2Provider) ) } + + await checkL2UpgadeExecutorInitialization( + UpgradeExecutor__factory.connect(l1.upgradeExecutor, l1Provider), + l1 + ) + + await checkL1Ownership(l1) + await checkL2Ownership(l2) }) }) //// L1 contracts -async function checkL1RouterInitialization(l1Router: L1GatewayRouter) { +async function checkL1RouterInitialization( + l1Router: L1GatewayRouter, + inbox: string, + l2: L2 +) { console.log('checkL1RouterInitialization') expect((await l1Router.defaultGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1ERC20Gateway.toLowerCase() - ) - - expect((await l1Router.inbox()).toLowerCase()).to.be.eq( - _l2Network.ethBridge.inbox.toLowerCase() + l2.standardGateway.toLowerCase() ) - + expect((await l1Router.inbox()).toLowerCase()).to.be.eq(inbox.toLowerCase()) expect((await l1Router.router()).toLowerCase()).to.be.eq( ethers.constants.AddressZero ) - expect((await l1Router.counterpartGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() + l2.router.toLowerCase() ) } async function checkL1StandardGatewayInitialization( - l1ERC20Gateway: L1ERC20Gateway + l1ERC20Gateway: L1ERC20Gateway, + l1: L1, + l2: L2 ) { console.log('checkL1StandardGatewayInitialization') expect((await l1ERC20Gateway.counterpartGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2ERC20Gateway.toLowerCase() + l2.standardGateway.toLowerCase() ) expect((await l1ERC20Gateway.router()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1GatewayRouter.toLowerCase() + l1.router.toLowerCase() ) expect((await l1ERC20Gateway.inbox()).toLowerCase()).to.be.eq( - _l2Network.ethBridge.inbox.toLowerCase() + l1.inbox.toLowerCase() ) expect((await l1ERC20Gateway.l2BeaconProxyFactory()).toLowerCase()).to.be.eq( ( await L2ERC20Gateway__factory.connect( await l1ERC20Gateway.counterpartGateway(), - _l2Provider + l2Provider ).beaconProxyFactory() ).toLowerCase() ) @@ -202,7 +181,7 @@ async function checkL1StandardGatewayInitialization( ( await BeaconProxyFactory__factory.connect( await l1ERC20Gateway.l2BeaconProxyFactory(), - _l2Provider + l2Provider ).cloneableProxyHash() ).toLowerCase() ) @@ -212,54 +191,73 @@ async function checkL1StandardGatewayInitialization( } async function checkL1CustomGatewayInitialization( - l1CustomGateway: L1CustomGateway + l1CustomGateway: L1CustomGateway, + l1: L1, + l2: L2 ) { console.log('checkL1CustomGatewayInitialization') expect((await l1CustomGateway.counterpartGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2CustomGateway.toLowerCase() + l2.customGateway.toLowerCase() ) expect((await l1CustomGateway.router()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1GatewayRouter.toLowerCase() + l1.router.toLowerCase() ) expect((await l1CustomGateway.inbox()).toLowerCase()).to.be.eq( - _l2Network.ethBridge.inbox.toLowerCase() + l1.inbox.toLowerCase() ) - // TODO - // owner check - expect((await l1CustomGateway.whitelist()).toLowerCase()).to.be.eq( ethers.constants.AddressZero ) } -async function checkL1WethGatewayInitialization(l1WethGateway: L1WethGateway) { +async function checkL1WethGatewayInitialization( + l1WethGateway: L1WethGateway, + l1: L1, + l2: L2 +) { console.log('checkL1WethGatewayInitialization') expect((await l1WethGateway.counterpartGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2WethGateway.toLowerCase() + l2.wethGateway.toLowerCase() ) expect((await l1WethGateway.router()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1GatewayRouter.toLowerCase() + l1.router.toLowerCase() ) expect((await l1WethGateway.inbox()).toLowerCase()).to.be.eq( - _l2Network.ethBridge.inbox.toLowerCase() + l1.inbox.toLowerCase() ) - expect((await l1WethGateway.l1Weth()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1Weth.toLowerCase() + expect((await l1WethGateway.l1Weth()).toLowerCase()).to.not.be.eq( + ethers.constants.AddressZero ) - expect((await l1WethGateway.l2Weth()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2Weth.toLowerCase() + expect((await l1WethGateway.l2Weth()).toLowerCase()).to.not.be.eq( + ethers.constants.AddressZero ) } +async function checkL2UpgadeExecutorInitialization( + l2Executor: UpgradeExecutor, + l1: L1 +) { + console.log('checkL2UpgadeExecutorInitialization') + + //// check assigned/revoked roles are correctly set + const adminRole = await l2Executor.ADMIN_ROLE() + const executorRole = await l2Executor.EXECUTOR_ROLE() + + expect(await l2Executor.hasRole(adminRole, l2Executor.address)).to.be.true + expect(await l2Executor.hasRole(executorRole, l1.rollupOwner)).to.be.true + expect(await l2Executor.hasRole(executorRole, applyAlias(l1.upgradeExecutor))) + .to.be.true +} + //// L2 contracts async function checkL2RouterInitialization(l2Router: L2GatewayRouter) { @@ -344,76 +342,66 @@ async function checkL2WethGatewayInitialization(l2WethGateway: L2WethGateway) { ) } -async function checkOwnership( - rollupOwner: string, - l1ProxyAdmin: ProxyAdmin, - l2ProxyAdmin: ProxyAdmin, - l1Router: L1GatewayRouter, - l1CustomGateway: L1CustomGateway -) { - console.log('checkL2ProxyAdminInitialization') +async function checkL1Ownership(l1: L1) { + console.log('checkL1Ownership') + + // check proxyAdmins + expect(await _getProxyAdmin(l1.router, l1Provider)).to.be.eq(l1.proxyAdmin) + expect(await _getProxyAdmin(l1.standardGateway, l1Provider)).to.be.eq( + l1.proxyAdmin + ) + expect(await _getProxyAdmin(l1.customGateway, l1Provider)).to.be.eq( + l1.proxyAdmin + ) + if (l1.wethGateway !== ethers.constants.AddressZero) { + expect(await _getProxyAdmin(l1.wethGateway, l1Provider)).to.be.eq( + l1.proxyAdmin + ) + } + expect(await _getProxyAdmin(l1.upgradeExecutor, l1Provider)).to.be.eq( + l1.proxyAdmin + ) - expect(rollupOwner).to.be.eq((await l1ProxyAdmin.owner()).toLowerCase()) - expect(rollupOwner).to.be.eq((await l2ProxyAdmin.owner()).toLowerCase()) - expect(rollupOwner).to.be.eq((await l1Router.owner()).toLowerCase()) - expect(rollupOwner).to.be.eq((await l1CustomGateway.owner()).toLowerCase()) + // check ownables + expect(await _getOwner(l1.proxyAdmin, l1Provider)).to.be.eq( + l1.upgradeExecutor + ) + expect(await _getOwner(l1.router, l1Provider)).to.be.eq(l1.upgradeExecutor) + expect(await _getOwner(l1.customGateway, l1Provider)).to.be.eq( + l1.upgradeExecutor + ) + expect(await _getOwner(l1.upgradeExecutor, l1Provider)).to.be.eq( + l1.upgradeExecutor + ) } -export const getProvidersAndSetupNetworks = async (setupConfig: { - l1Url: string - l2Url: string - networkFilename?: string -}): Promise<{ - l1Network: L1Network - l2Network: L2Network - l1Provider: JsonRpcProvider - l2Provider: JsonRpcProvider -}> => { - const l1Provider = new JsonRpcProvider(setupConfig.l1Url) - const l2Provider = new JsonRpcProvider(setupConfig.l2Url) - - if (setupConfig.networkFilename) { - // check if theres an existing network available - const localNetworkFile = path.join( - __dirname, - '..', - setupConfig.networkFilename - ) - if (fs.existsSync(localNetworkFile)) { - const { l1Network, l2Network } = JSON.parse( - fs.readFileSync(localNetworkFile).toString() - ) as { - l1Network: L1Network - l2Network: L2Network - } +async function checkL2Ownership(l2: L2) { + console.log('checkL2Ownership') - const existingL1Network = l1Networks[l1Network.chainID.toString()] - const existingL2Network = l2Networks[l2Network.chainID.toString()] - if (!existingL2Network) { - addCustomNetwork({ - // dont add the l1 network if it's already been added - customL1Network: existingL1Network ? undefined : l1Network, - customL2Network: l2Network, - }) - } + const l2ProxyAdmin = await _getProxyAdmin(l2.router, l2Provider) - return { - l1Network, - l1Provider, - l2Network, - l2Provider, - } - } else throw Error(`Missing file ${localNetworkFile}`) - } else { - return { - l1Network: await getL1Network(l1Provider), - l1Provider, - l2Network: await getL2Network(l2Provider), - l2Provider, - } + // check proxyAdmins + expect(await _getProxyAdmin(l2.router, l2Provider)).to.be.eq(l2ProxyAdmin) + expect(await _getProxyAdmin(l2.standardGateway, l2Provider)).to.be.eq( + l2ProxyAdmin + ) + expect(await _getProxyAdmin(l2.customGateway, l2Provider)).to.be.eq( + l2ProxyAdmin + ) + if (l2.wethGateway !== ethers.constants.AddressZero) { + expect(await _getProxyAdmin(l2.wethGateway, l2Provider)).to.be.eq( + l2ProxyAdmin + ) } + expect(await _getProxyAdmin(l2.upgradeExecutor, l2Provider)).to.be.eq( + l2ProxyAdmin + ) + + // check ownables + expect(await _getOwner(l2ProxyAdmin, l2Provider)).to.be.eq(l2.upgradeExecutor) } +//// utils async function isUsingFeeToken(inbox: string, l1Provider: JsonRpcProvider) { const bridge = await IInbox__factory.connect(inbox, l1Provider).bridge() @@ -425,3 +413,144 @@ async function isUsingFeeToken(inbox: string, l1Provider: JsonRpcProvider) { return true } + +async function _getTokenBridgeAddresses( + rollupAddress: string, + l1TokenBridgeCreatorAddress: string +) { + const inboxAddress = await RollupCore__factory.connect( + rollupAddress, + l1Provider + ).inbox() + + const l1TokenBridgeCreator = L1AtomicTokenBridgeCreator__factory.connect( + l1TokenBridgeCreatorAddress, + l1Provider + ) + + //// L1 + // find all the events emitted by this address + const filter: ethers.providers.Filter = { + address: l1TokenBridgeCreatorAddress, + topics: [ + ethers.utils.id('OrbitTokenBridgeCreated'), + ethers.utils.hexZeroPad(inboxAddress, 32), + ], + } + + const currentBlock = await l1Provider.getBlockNumber() + const fromBlock = currentBlock - 100000 // ~last 24h on + const logs = await l1Provider.getLogs({ + ...filter, + fromBlock: fromBlock, + toBlock: 'latest', + }) + + if (logs.length === 0) { + throw new Error("Couldn't find any OrbitTokenBridgeCreated events") + } + + const logData = l1TokenBridgeCreator.interface.parseLog(logs[0]) + console.log(logData) + + const { + inbox, + owner, + router, + standardGateway, + customGateway, + wethGateway, + proxyAdmin, + upgradeExecutor, + } = logData.args + const l1 = { + inbox, + rollupOwner: owner, + router, + standardGateway, + customGateway, + wethGateway, + proxyAdmin, + upgradeExecutor, + } + + //// L2 + const l2 = { + router: await l1TokenBridgeCreator.getCanonicalL2RouterAddress(), + standardGateway: + await l1TokenBridgeCreator.getCanonicalL2StandardGatewayAddress(), + customGateway: + await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress(), + wethGateway: await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(), + weth: await l1TokenBridgeCreator.getCanonicalL2WethAddress(), + upgradeExecutor: + await l1TokenBridgeCreator.getCanonicalL2UpgradeExecutorAddress(), + } + + return { + l1, + l2, + } +} + +async function _getProxyAdmin( + contractAddress: string, + provider: Provider +): Promise { + return _getAddressAtStorageSlot( + contractAddress, + provider, + '0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103' + ) +} + +async function _getOwner( + contractAddress: string, + provider: Provider +): Promise { + return ( + await IOwnable__factory.connect(contractAddress, provider).owner() + ).toLowerCase() +} + +async function _getAddressAtStorageSlot( + contractAddress: string, + provider: Provider, + storageSlotBytes: string +): Promise { + const storageValue = await provider.getStorageAt( + contractAddress, + storageSlotBytes + ) + + if (!storageValue) { + return '' + } + + // remove excess bytes + const formatAddress = + storageValue.substring(0, 2) + storageValue.substring(26) + + // return address as checksum address + return ethers.utils.getAddress(formatAddress) +} + +interface L1 { + inbox: string + rollupOwner: string + router: string + standardGateway: string + customGateway: string + wethGateway: string + proxyAdmin: string + upgradeExecutor: string +} + +interface L2 { + router: string + standardGateway: string + customGateway: string + wethGateway: string + weth: string + upgradeExecutor: string +} From c4c517d32d8d2ce7945ce203e131132a0c446128 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 7 Aug 2023 08:43:21 +0200 Subject: [PATCH 142/163] Fix deployment test --- .../goerli-deployment/createTokenBridge.ts | 2 +- test-e2e/tokenBridgeDeploymentTest.ts | 94 ++++++++++++------- 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts index 88d0b0f352..7c43afae5e 100644 --- a/scripts/goerli-deployment/createTokenBridge.ts +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -14,7 +14,7 @@ export const envVars = { childChainRpc: process.env['ORBIT_RPC'] as string, } -const L1_TOKEN_BRIDGE_CREATOR = '0x4Ba3aC2a2fEf26eAA6d05D71B79fde08Cb3078a9' +const L1_TOKEN_BRIDGE_CREATOR = '0x24c77cb51F7a51fB8B69a83a8e36a2fd01B81D82' /** * Steps: diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index 4d18ad297b..75ac58b487 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -1,4 +1,4 @@ -import { JsonRpcProvider, Provider } from '@ethersproject/providers' +import { JsonRpcProvider, Provider, Filter } from '@ethersproject/providers' import { BeaconProxyFactory__factory, IERC20Bridge__factory, @@ -69,16 +69,11 @@ describe('tokenBridge', () => { l1TokenBridgeCreator ) - // console.log(l1) - // console.log('############') - // console.log(l2) - // exit() - //// L1 checks await checkL1RouterInitialization( L1GatewayRouter__factory.connect(l1.router, l1Provider), - l1.inbox, + l1, l2 ) @@ -105,20 +100,28 @@ describe('tokenBridge', () => { //// L2 checks await checkL2RouterInitialization( - L2GatewayRouter__factory.connect(l2.router, l2Provider) + L2GatewayRouter__factory.connect(l2.router, l2Provider), + l1, + l2 ) await checkL2StandardGatewayInitialization( - L2ERC20Gateway__factory.connect(l2.standardGateway, l2Provider) + L2ERC20Gateway__factory.connect(l2.standardGateway, l2Provider), + l1, + l2 ) await checkL2CustomGatewayInitialization( - L2CustomGateway__factory.connect(l2.customGateway, l2Provider) + L2CustomGateway__factory.connect(l2.customGateway, l2Provider), + l1, + l2 ) if (!usingFeeToken) { await checkL2WethGatewayInitialization( - L2WethGateway__factory.connect(l2.wethGateway, l2Provider) + L2WethGateway__factory.connect(l2.wethGateway, l2Provider), + l1, + l2 ) } @@ -136,15 +139,17 @@ describe('tokenBridge', () => { async function checkL1RouterInitialization( l1Router: L1GatewayRouter, - inbox: string, + l1: L1, l2: L2 ) { console.log('checkL1RouterInitialization') expect((await l1Router.defaultGateway()).toLowerCase()).to.be.eq( - l2.standardGateway.toLowerCase() + l1.standardGateway.toLowerCase() + ) + expect((await l1Router.inbox()).toLowerCase()).to.be.eq( + l1.inbox.toLowerCase() ) - expect((await l1Router.inbox()).toLowerCase()).to.be.eq(inbox.toLowerCase()) expect((await l1Router.router()).toLowerCase()).to.be.eq( ethers.constants.AddressZero ) @@ -260,11 +265,15 @@ async function checkL2UpgadeExecutorInitialization( //// L2 contracts -async function checkL2RouterInitialization(l2Router: L2GatewayRouter) { +async function checkL2RouterInitialization( + l2Router: L2GatewayRouter, + l1: L1, + l2: L2 +) { console.log('checkL2RouterInitialization') expect((await l2Router.defaultGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2ERC20Gateway.toLowerCase() + l2.standardGateway.toLowerCase() ) expect((await l2Router.router()).toLowerCase()).to.be.eq( @@ -272,28 +281,30 @@ async function checkL2RouterInitialization(l2Router: L2GatewayRouter) { ) expect((await l2Router.counterpartGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1GatewayRouter.toLowerCase() + l1.router.toLowerCase() ) } async function checkL2StandardGatewayInitialization( - l2ERC20Gateway: L2ERC20Gateway + l2ERC20Gateway: L2ERC20Gateway, + l1: L1, + l2: L2 ) { console.log('checkL2StandardGatewayInitialization') expect((await l2ERC20Gateway.counterpartGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1ERC20Gateway.toLowerCase() + l1.standardGateway.toLowerCase() ) expect((await l2ERC20Gateway.router()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() + l2.router.toLowerCase() ) expect((await l2ERC20Gateway.beaconProxyFactory()).toLowerCase()).to.be.eq( ( await L1ERC20Gateway__factory.connect( await l2ERC20Gateway.counterpartGateway(), - _l1Provider + l1Provider ).l2BeaconProxyFactory() ).toLowerCase() ) @@ -302,43 +313,49 @@ async function checkL2StandardGatewayInitialization( ( await L1ERC20Gateway__factory.connect( await l2ERC20Gateway.counterpartGateway(), - _l1Provider + l1Provider ).cloneableProxyHash() ).toLowerCase() ) } async function checkL2CustomGatewayInitialization( - l2CustomGateway: L2CustomGateway + l2CustomGateway: L2CustomGateway, + l1: L1, + l2: L2 ) { console.log('checkL2CustomGatewayInitialization') expect((await l2CustomGateway.counterpartGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1CustomGateway.toLowerCase() + l1.customGateway.toLowerCase() ) expect((await l2CustomGateway.router()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() + l2.router.toLowerCase() ) } -async function checkL2WethGatewayInitialization(l2WethGateway: L2WethGateway) { +async function checkL2WethGatewayInitialization( + l2WethGateway: L2WethGateway, + l1: L1, + l2: L2 +) { console.log('checkL2WethGatewayInitialization') expect((await l2WethGateway.counterpartGateway()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1WethGateway.toLowerCase() + l1.wethGateway.toLowerCase() ) expect((await l2WethGateway.router()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2GatewayRouter.toLowerCase() + l2.router.toLowerCase() ) - expect((await l2WethGateway.l1Weth()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l1Weth.toLowerCase() + expect((await l2WethGateway.l1Weth()).toLowerCase()).to.not.be.eq( + ethers.constants.AddressZero ) - expect((await l2WethGateway.l2Weth()).toLowerCase()).to.be.eq( - _l2Network.tokenBridge.l2Weth.toLowerCase() + expect((await l2WethGateway.l2Weth()).toLowerCase()).to.not.be.eq( + ethers.constants.AddressZero ) } @@ -430,10 +447,12 @@ async function _getTokenBridgeAddresses( //// L1 // find all the events emitted by this address - const filter: ethers.providers.Filter = { + const filter: Filter = { address: l1TokenBridgeCreatorAddress, topics: [ - ethers.utils.id('OrbitTokenBridgeCreated'), + ethers.utils.id( + 'OrbitTokenBridgeCreated(address,address,address,address,address,address,address,address)' + ), ethers.utils.hexZeroPad(inboxAddress, 32), ], } @@ -447,11 +466,14 @@ async function _getTokenBridgeAddresses( }) if (logs.length === 0) { - throw new Error("Couldn't find any OrbitTokenBridgeCreated events") + throw new Error( + "Couldn't find any OrbitTokenBridgeCreated events in block range[" + + fromBlock + + ',latest]' + ) } const logData = l1TokenBridgeCreator.interface.parseLog(logs[0]) - console.log(logData) const { inbox, From 38083c721bd7ac400a401014f748fa6a3ec26534 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 7 Aug 2023 09:07:31 +0200 Subject: [PATCH 143/163] Use lower case in tests --- test-e2e/tokenBridgeDeploymentTest.ts | 70 +++++++++++++++------------ 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index 75ac58b487..d5db13e487 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -125,8 +125,8 @@ describe('tokenBridge', () => { ) } - await checkL2UpgadeExecutorInitialization( - UpgradeExecutor__factory.connect(l1.upgradeExecutor, l1Provider), + await checkL2UpgradeExecutorInitialization( + UpgradeExecutor__factory.connect(l2.upgradeExecutor, l2Provider), l1 ) @@ -247,11 +247,11 @@ async function checkL1WethGatewayInitialization( ) } -async function checkL2UpgadeExecutorInitialization( +async function checkL2UpgradeExecutorInitialization( l2Executor: UpgradeExecutor, l1: L1 ) { - console.log('checkL2UpgadeExecutorInitialization') + console.log('checkL2UpgradeExecutorInitialization') //// check assigned/revoked roles are correctly set const adminRole = await l2Executor.ADMIN_ROLE() @@ -259,8 +259,8 @@ async function checkL2UpgadeExecutorInitialization( expect(await l2Executor.hasRole(adminRole, l2Executor.address)).to.be.true expect(await l2Executor.hasRole(executorRole, l1.rollupOwner)).to.be.true - expect(await l2Executor.hasRole(executorRole, applyAlias(l1.upgradeExecutor))) - .to.be.true + const aliasedL1Executor = applyAlias(l1.upgradeExecutor) + expect(await l2Executor.hasRole(executorRole, aliasedL1Executor)).to.be.true } //// L2 contracts @@ -387,9 +387,6 @@ async function checkL1Ownership(l1: L1) { expect(await _getOwner(l1.customGateway, l1Provider)).to.be.eq( l1.upgradeExecutor ) - expect(await _getOwner(l1.upgradeExecutor, l1Provider)).to.be.eq( - l1.upgradeExecutor - ) } async function checkL2Ownership(l2: L2) { @@ -486,27 +483,36 @@ async function _getTokenBridgeAddresses( upgradeExecutor, } = logData.args const l1 = { - inbox, - rollupOwner: owner, - router, - standardGateway, - customGateway, - wethGateway, - proxyAdmin, - upgradeExecutor, + inbox: inbox.toLowerCase(), + rollupOwner: owner.toLowerCase(), + router: router.toLowerCase(), + standardGateway: standardGateway.toLowerCase(), + customGateway: customGateway.toLowerCase(), + wethGateway: wethGateway.toLowerCase(), + proxyAdmin: proxyAdmin.toLowerCase(), + upgradeExecutor: upgradeExecutor.toLowerCase(), } //// L2 const l2 = { - router: await l1TokenBridgeCreator.getCanonicalL2RouterAddress(), - standardGateway: - await l1TokenBridgeCreator.getCanonicalL2StandardGatewayAddress(), - customGateway: - await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress(), - wethGateway: await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(), - weth: await l1TokenBridgeCreator.getCanonicalL2WethAddress(), - upgradeExecutor: - await l1TokenBridgeCreator.getCanonicalL2UpgradeExecutorAddress(), + router: ( + await l1TokenBridgeCreator.getCanonicalL2RouterAddress() + ).toLowerCase(), + standardGateway: ( + await l1TokenBridgeCreator.getCanonicalL2StandardGatewayAddress() + ).toLowerCase(), + customGateway: ( + await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress() + ).toLowerCase(), + wethGateway: ( + await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress() + ).toLowerCase(), + weth: ( + await l1TokenBridgeCreator.getCanonicalL2WethAddress() + ).toLowerCase(), + upgradeExecutor: ( + await l1TokenBridgeCreator.getCanonicalL2UpgradeExecutorAddress() + ).toLowerCase(), } return { @@ -519,11 +525,13 @@ async function _getProxyAdmin( contractAddress: string, provider: Provider ): Promise { - return _getAddressAtStorageSlot( - contractAddress, - provider, - '0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103' - ) + return ( + await _getAddressAtStorageSlot( + contractAddress, + provider, + '0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103' + ) + ).toLowerCase() } async function _getOwner( From 3ca96b2b9724de53c206482d2b7bcf3fab0e0bfe Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Mon, 7 Aug 2023 15:59:04 +0200 Subject: [PATCH 144/163] Don't check weth stuff in case of fee token --- scripts/goerli-deployment/createTokenBridge.ts | 2 +- test-e2e/tokenBridgeDeploymentTest.ts | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts index 7c43afae5e..016c4e233f 100644 --- a/scripts/goerli-deployment/createTokenBridge.ts +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -14,7 +14,7 @@ export const envVars = { childChainRpc: process.env['ORBIT_RPC'] as string, } -const L1_TOKEN_BRIDGE_CREATOR = '0x24c77cb51F7a51fB8B69a83a8e36a2fd01B81D82' +const L1_TOKEN_BRIDGE_CREATOR = '0xc9CDf2425961e232FdBA51650A729710de7bfa69' /** * Steps: diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index d5db13e487..2dbecdffe2 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -402,7 +402,8 @@ async function checkL2Ownership(l2: L2) { expect(await _getProxyAdmin(l2.customGateway, l2Provider)).to.be.eq( l2ProxyAdmin ) - if (l2.wethGateway !== ethers.constants.AddressZero) { + + if (l2.wethGateway != ethers.constants.AddressZero) { expect(await _getProxyAdmin(l2.wethGateway, l2Provider)).to.be.eq( l2ProxyAdmin ) @@ -493,6 +494,8 @@ async function _getTokenBridgeAddresses( upgradeExecutor: upgradeExecutor.toLowerCase(), } + const usingFeeToken = await isUsingFeeToken(l1.inbox, l1Provider) + //// L2 const l2 = { router: ( @@ -504,11 +507,13 @@ async function _getTokenBridgeAddresses( customGateway: ( await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress() ).toLowerCase(), - wethGateway: ( - await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress() + wethGateway: (usingFeeToken + ? ethers.constants.AddressZero + : await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress() ).toLowerCase(), - weth: ( - await l1TokenBridgeCreator.getCanonicalL2WethAddress() + weth: (usingFeeToken + ? ethers.constants.AddressZero + : await l1TokenBridgeCreator.getCanonicalL2WethAddress() ).toLowerCase(), upgradeExecutor: ( await l1TokenBridgeCreator.getCanonicalL2UpgradeExecutorAddress() From d5998c2c6a4bf5a3171dc74166acf7a0f22dba26 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 18 Aug 2023 13:51:38 +0200 Subject: [PATCH 145/163] Use upgrade executor from npm package --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 4 +- .../ethereum/L1AtomicTokenBridgeCreator.sol | 5 +- .../tokenbridge/libraries/UpgradeExecutor.sol | 57 --- lib/nitro-contracts | 2 +- package.json | 3 +- scripts/atomicTokenBridgeDeployer.ts | 15 +- test-e2e/tokenBridgeDeploymentTest.ts | 14 +- yarn.lock | 365 ++++++++++++------ 8 files changed, 271 insertions(+), 194 deletions(-) delete mode 100644 contracts/tokenbridge/libraries/UpgradeExecutor.sol diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index ae817ec81e..0838ea148a 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -6,7 +6,7 @@ import {L2ERC20Gateway} from "./gateway/L2ERC20Gateway.sol"; import {L2CustomGateway} from "./gateway/L2CustomGateway.sol"; import {L2WethGateway} from "./gateway/L2WethGateway.sol"; import {StandardArbERC20} from "./StandardArbERC20.sol"; -import {UpgradeExecutor} from "../libraries/UpgradeExecutor.sol"; +import {IUpgradeExecutor} from "@offchainlabs/upgrade-executor/src/IUpgradeExecutor.sol"; import {BeaconProxyFactory} from "../libraries/ClonableBeaconProxy.sol"; import {aeWETH} from "../libraries/aeWETH.sol"; import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; @@ -87,7 +87,7 @@ contract L2AtomicTokenBridgeFactory { address[] memory executors = new address[](2); executors[0] = rollupOwner; executors[1] = aliasedL1UpgradeExecutor; - UpgradeExecutor(canonicalUpgradeExecutor).initialize(canonicalUpgradeExecutor, executors); + IUpgradeExecutor(canonicalUpgradeExecutor).initialize(canonicalUpgradeExecutor, executors); return canonicalUpgradeExecutor; } diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index cbb4b71744..3f78bee7d3 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -17,7 +17,6 @@ import {L1WethGateway} from "./gateway/L1WethGateway.sol"; import {L1OrbitGatewayRouter} from "./gateway/L1OrbitGatewayRouter.sol"; import {L1OrbitERC20Gateway} from "./gateway/L1OrbitERC20Gateway.sol"; import {L1OrbitCustomGateway} from "./gateway/L1OrbitCustomGateway.sol"; - import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { @@ -28,7 +27,7 @@ import { ProxyAdmin } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import {BytesLib} from "../libraries/BytesLib.sol"; -import {UpgradeExecutor} from "../libraries/UpgradeExecutor.sol"; +import {IUpgradeExecutor} from "@offchainlabs/upgrade-executor/src/IUpgradeExecutor.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; @@ -73,7 +72,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { L1OrbitGatewayRouter feeTokenBasedRouterTemplate; L1OrbitERC20Gateway feeTokenBasedStandardGatewayTemplate; L1OrbitCustomGateway feeTokenBasedCustomGatewayTemplate; - UpgradeExecutor upgradeExecutor; + IUpgradeExecutor upgradeExecutor; } // non-canonical router registry diff --git a/contracts/tokenbridge/libraries/UpgradeExecutor.sol b/contracts/tokenbridge/libraries/UpgradeExecutor.sol deleted file mode 100644 index ada8c6ded1..0000000000 --- a/contracts/tokenbridge/libraries/UpgradeExecutor.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.4; - -import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; - -/// @title A root contract from which it execute upgrades -/// @notice Does not contain upgrade logic itself, only the means to call upgrade contracts and execute them -/// @dev We use these upgrade contracts as they allow multiple actions to take place in an upgrade -/// and for these actions to interact. However because we are delegatecalling into these upgrade -/// contracts, it's important that these upgrade contract do not touch or modify contract state. -contract UpgradeExecutor is Initializable, AccessControlUpgradeable, ReentrancyGuard { - using Address for address; - - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); - bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); - - /// @notice Emitted when an upgrade execution occurs - event UpgradeExecuted(address indexed upgrade, uint256 value, bytes data); - - /// @notice Initialise the upgrade executor - /// @param admin The admin who can update other roles, and itself - ADMIN_ROLE - /// @param executors Can call the execute function - EXECUTOR_ROLE - function initialize(address admin, address[] memory executors) public initializer { - require(admin != address(0), "UpgradeExecutor: zero admin"); - - __AccessControl_init(); - - _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE); - _setRoleAdmin(EXECUTOR_ROLE, ADMIN_ROLE); - - _setupRole(ADMIN_ROLE, admin); - for (uint256 i = 0; i < executors.length; ++i) { - _setupRole(EXECUTOR_ROLE, executors[i]); - } - } - - /// @notice Execute an upgrade by delegate calling an upgrade contract - /// @dev Only executor can call this. Since we're using a delegatecall here the Upgrade contract - /// will have access to the state of this contract - including the roles. Only upgrade contracts - /// that do not touch local state should be used. - function execute(address upgrade, bytes memory upgradeCallData) - public - payable - onlyRole(EXECUTOR_ROLE) - nonReentrant - { - // OZ Address library check if the address is a contract and bubble up inner revert reason - address(upgrade).functionDelegateCall( - upgradeCallData, - "UpgradeExecutor: inner delegate call failed without reason" - ); - - emit UpgradeExecuted(upgrade, msg.value, upgradeCallData); - } -} diff --git a/lib/nitro-contracts b/lib/nitro-contracts index 1aa6599566..570e8180ad 160000 --- a/lib/nitro-contracts +++ b/lib/nitro-contracts @@ -1 +1 @@ -Subproject commit 1aa65995664346a3ad5e874fd3581a4d6f34b734 +Subproject commit 570e8180ade4e89b9a2e369afe4fa61f09d35fb6 diff --git a/package.json b/package.json index 5edc0b423d..a3383d740f 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "@arbitrum/nitro-contracts": "^1.0.0-beta.8", "@arbitrum/sdk": "^3.1.5", "@openzeppelin/contracts": "4.8.3", - "@openzeppelin/contracts-upgradeable": "4.8.3" + "@openzeppelin/contracts-upgradeable": "4.8.3", + "@offchainlabs/upgrade-executor": "^1.0.0-beta.2" }, "devDependencies": { "@arbitrum/sdk": "^3.1.3", diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index b062dc3f98..598b04386d 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -21,8 +21,11 @@ import { IInbox__factory, IERC20Bridge__factory, IERC20__factory, - UpgradeExecutor__factory, } from '../build/types' +import { + abi as UpgradeExecutorABI, + bytecode as UpgradeExecutorBytecode, +} from '@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/UpgradeExecutor.json' import { JsonRpcProvider } from '@ethersproject/providers' import { L1ToL2MessageGasEstimator, @@ -75,7 +78,7 @@ export const createTokenBridge = async ( customGateway: L2CustomGateway__factory.bytecode, wethGateway: L2WethGateway__factory.bytecode, aeWeth: AeWETH__factory.bytecode, - upgradeExecutor: UpgradeExecutor__factory.bytecode, + upgradeExecutor: UpgradeExecutorBytecode, } const gasEstimateToDeployContracts = await l2FactoryTemplate.estimateGas.deployL2Contracts( @@ -304,10 +307,12 @@ export const deployL1TokenBridgeCreator = async ( await new L1OrbitCustomGateway__factory(l1Deployer).deploy() await feeTokenBasedCustomGatewayTemplate.deployed() - const upgradeExecutor = await new UpgradeExecutor__factory( + const upgradeExecutor = new ethers.ContractFactory( + UpgradeExecutorABI, + UpgradeExecutorBytecode, l1Deployer - ).deploy() - await upgradeExecutor.deployed() + ) + await upgradeExecutor.deploy() const l1Templates = { routerTemplate: routerTemplate.address, diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index 2dbecdffe2..972cc3ced2 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -21,15 +21,15 @@ import { L2GatewayRouter__factory, L2WethGateway, L2WethGateway__factory, - UpgradeExecutor, - UpgradeExecutor__factory, } from '../build/types' +import { abi as UpgradeExecutorABI } from '@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/UpgradeExecutor.json' import { RollupCore__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupCore__factory' import { applyAlias } from '../test/testhelper' import path from 'path' import fs from 'fs' import { expect } from 'chai' import { ethers } from 'hardhat' +import { Contract } from 'ethers' const config = { l1Url: process.env.BASECHAIN_RPC || 'http://localhost:8545', @@ -125,10 +125,12 @@ describe('tokenBridge', () => { ) } - await checkL2UpgradeExecutorInitialization( - UpgradeExecutor__factory.connect(l2.upgradeExecutor, l2Provider), - l1 + const upgExecutor = new ethers.Contract( + l2.upgradeExecutor, + UpgradeExecutorABI, + l2Provider ) + await checkL2UpgradeExecutorInitialization(upgExecutor, l1) await checkL1Ownership(l1) await checkL2Ownership(l2) @@ -248,7 +250,7 @@ async function checkL1WethGatewayInitialization( } async function checkL2UpgradeExecutorInitialization( - l2Executor: UpgradeExecutor, + l2Executor: Contract, l1: L1 ) { console.log('checkL2UpgradeExecutorInitialization') diff --git a/yarn.lock b/yarn.lock index a8e1cf4d80..173faa53e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,9 +24,9 @@ sol2uml "2.2.0" "@arbitrum/sdk@^3.1.5": - version "3.1.6" - resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.6.tgz#0a64728040bd1ca4d6d8024946991308d248f303" - integrity sha512-wY7RHmvY26yc/OuwpJY+kjgAmUJZDGDXaQxfSQTp2t6sSFO+8oFFVsKIthBCY2RpDGFUVTGpRjCUEXiuJ6/SFA== + version "3.1.7" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.7.tgz#a543ec105cff68c05165fd5af377fb9f14282b98" + integrity sha512-ITuVvNPpvjlgEk8CKgexkfkEtKvL1eRZUTgqavenjOS8egZuklMoyDnJ08yG4KU+cOQW11dv2eepWDcvbR/NmQ== dependencies: "@ethersproject/address" "^5.0.8" "@ethersproject/bignumber" "^5.1.1" @@ -41,24 +41,25 @@ "@babel/highlight" "^7.10.4" "@babel/code-frame@^7.0.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" - integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.10.tgz#1c20e612b768fefa75f6e90d6ecb86329247f0a3" + integrity sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA== dependencies: - "@babel/highlight" "^7.22.5" + "@babel/highlight" "^7.22.10" + chalk "^2.4.2" "@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== -"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" - integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== +"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7" + integrity sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ== dependencies: "@babel/helper-validator-identifier" "^7.22.5" - chalk "^2.0.0" + chalk "^2.4.2" js-tokens "^4.0.0" "@colors/colors@1.5.0": @@ -215,6 +216,11 @@ ethereumjs-util "^7.1.1" miller-rabin "^4.0.0" +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + "@ethereumjs/tx@3.3.2": version "3.3.2" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.2.tgz#348d4624bf248aaab6c44fec2ae67265efe3db00" @@ -231,6 +237,15 @@ "@ethereumjs/common" "^2.6.4" ethereumjs-util "^7.1.5" +"@ethereumjs/util@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" + integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" + "@ethereumjs/vm@^5.9.0": version "5.9.3" resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.9.3.tgz#6d69202e4c132a4a1e1628ac246e92062e230823" @@ -649,11 +664,23 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" +"@noble/curves@1.1.0", "@noble/curves@~1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" + integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== + dependencies: + "@noble/hashes" "1.3.1" + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== +"@noble/hashes@1.3.1", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + "@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": version "1.7.1" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" @@ -706,11 +733,24 @@ 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/upgrade-executor@^1.0.0-beta.2": + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/@offchainlabs/upgrade-executor/-/upgrade-executor-1.0.0-beta.2.tgz#b3f9e1ba2e58edf17019249b4663d88567961fec" + integrity sha512-aSjWctspD2QTGXUv0fRHudFrl5oR42nRB/88JUnC9O5tujPyRksM6Y8WyrDNl3eZuqV+L1V76Ui2Av4NrUkd+g== + dependencies: + "@openzeppelin/contracts" "4.7.3" + "@openzeppelin/contracts-upgradeable" "4.7.3" + "@openzeppelin/contracts-upgradeable@4.5.2": version "4.5.2" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.5.2.tgz#90d9e47bacfd8693bfad0ac8a394645575528d05" integrity sha512-xgWZYaPlrEOQo3cBj97Ufiuv79SPd8Brh4GcFYhPgb6WvAq4ppz8dWKL6h+jLAK01rUqMRp/TS9AdXgAeNvCLA== +"@openzeppelin/contracts-upgradeable@4.7.3": + version "4.7.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz#f1d606e2827d409053f3e908ba4eb8adb1dd6995" + integrity sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A== + "@openzeppelin/contracts-upgradeable@4.8.3": version "4.8.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.3.tgz#6b076a7b751811b90fe3a172a7faeaa603e13a3f" @@ -721,24 +761,29 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.5.0.tgz#3fd75d57de172b3743cdfc1206883f56430409cc" integrity sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA== +"@openzeppelin/contracts@4.7.3": + version "4.7.3" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.7.3.tgz#939534757a81f8d69cc854c7692805684ff3111e" + integrity sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw== + "@openzeppelin/contracts@4.8.3": version "4.8.3" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.3.tgz#cbef3146bfc570849405f59cba18235da95a252a" integrity sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg== "@openzeppelin/upgrades-core@^1.24.1": - version "1.27.3" - resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.27.3.tgz#d5578e3a3ccd18a61fc585945be67951480238b5" - integrity sha512-IqlSMUkno1XKF4L46aUqZ4BqHxj4dF0BRGrFcKeG2Q0vrsKoazhY67JG9bO+wMYG4zxl6jgmG0bd5ef9HLcLmw== + version "1.28.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.28.0.tgz#19405f272dc09e766c756d9d149cbd680168aef7" + integrity sha512-8RKlyg98Adv+46GxDaR0awL3R8bVCcQ27DcSEwrgWOp6siHh8sZg4a2l+2dhPl1510S6uBfhHSydMH5VX2BV5g== dependencies: - cbor "^8.0.0" + cbor "^9.0.0" chalk "^4.1.0" compare-versions "^6.0.0" debug "^4.1.1" ethereumjs-util "^7.0.3" minimist "^1.2.7" proper-lockfile "^4.1.1" - solidity-ast "^0.4.15" + solidity-ast "^0.4.26" "@resolver-engine/core@^0.3.3": version "0.3.3" @@ -791,6 +836,15 @@ "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" +"@scure/bip32@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" + integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== + dependencies: + "@noble/curves" "~1.1.0" + "@noble/hashes" "~1.3.1" + "@scure/base" "~1.1.0" + "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" @@ -799,6 +853,14 @@ "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -891,14 +953,7 @@ dependencies: antlr4ts "^0.5.0-alpha.4" -"@solidity-parser/parser@^0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.15.0.tgz#1d359be40be84f174dd616ccfadcf43346c6bf63" - integrity sha512-5UFJJTzWi1hgFk6aGCZ5rxG2DJkCJOzJ74qg7UkWSNCDSigW+CJLoYUb5bLiKrtI34Nr9rpFSUNHfkqtlL+N/w== - dependencies: - antlr4ts "^0.5.0-alpha.4" - -"@solidity-parser/parser@^0.16.0": +"@solidity-parser/parser@^0.16.0", "@solidity-parser/parser@^0.16.1": version "0.16.1" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.1.tgz#f7c8a686974e1536da0105466c4db6727311253c" integrity sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw== @@ -932,9 +987,9 @@ integrity sha512-sE7c9IHIGdbK4YayH4BC8i8qMjoAOeg6nUXUDZZp8wlU21/EMpaG+CLx+KqcIPyR+GSWIW3Dm0PXkr2nlggFDA== "@truffle/interface-adapter@^0.5.25": - version "0.5.34" - resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.34.tgz#a45edc23d6ace0e01ebf237b668119f456729643" - integrity sha512-gPxabfMi2TueE4VxnNuyeudOfvGJQ1ofVC02PFw14cnRQhzH327JikjjQbZ1bT6S7kWl9H6P3hQPFeYFMHdm1g== + version "0.5.35" + resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.35.tgz#f0eb1c4a2803190ca249143f545029a8b641fe96" + integrity sha512-B5gtJnvsum5j2do393n0UfCT8MklrlAZxuqvEFBeMM9UKnreYct0/D368FVMlZwWo1N50HgGeZ0hlpSJqR/nvg== dependencies: bn.js "^5.1.3" ethers "^4.0.32" @@ -1122,9 +1177,9 @@ form-data "^3.0.0" "@types/node@*": - version "20.4.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.2.tgz#129cc9ae69f93824f92fac653eebfb4812ab4af9" - integrity sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw== + version "20.5.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.0.tgz#7fc8636d5f1aaa3b21e6245e97d56b7f56702313" + integrity sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q== "@types/node@^10.0.3": version "10.17.60" @@ -1137,9 +1192,9 @@ integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== "@types/node@^14.14.28": - version "14.18.53" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.53.tgz#42855629b8773535ab868238718745bf56c56219" - integrity sha512-soGmOpVBUq+gaBMwom1M+krC/NNbWlosh4AtGA03SyWNDiqSKtwp7OulO1M6+mg8YkHMvJ/y0AkCeO8d1hNb7A== + version "14.18.54" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.54.tgz#fc304bd66419030141fa997dc5a9e0e374029ae8" + integrity sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw== "@types/node@^8.0.0": version "8.10.66" @@ -1670,6 +1725,18 @@ array.prototype.reduce@^1.0.5: es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" +arraybuffer.prototype.slice@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb" + integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -2762,22 +2829,29 @@ camelcase@^6.0.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30000844: - version "1.0.30001515" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001515.tgz#418aefeed9d024cd3129bfae0ccc782d4cb8f12b" - integrity sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA== + version "1.0.30001521" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001521.tgz#e9930cf499f7c1e80334b6c1fbca52e00d889e56" + integrity sha512-fnx1grfpEOvDGH+V17eccmNjucGUnCbP6KL+l5KqBIerp26WK/+RQ7CIDE37KGJjaPyqWXXlFUyKiWmvdNNKmQ== caseless@^0.12.0, caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -cbor@^8.0.0, cbor@^8.1.0: +cbor@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== dependencies: nofilter "^3.1.0" +cbor@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-9.0.1.tgz#b16e393d4948d44758cd54ac6151379d443b37ae" + integrity sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ== + dependencies: + nofilter "^3.1.0" + chai@^4.2.0: version "4.3.7" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" @@ -2802,7 +2876,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3082,6 +3156,11 @@ commander@^10.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +commander@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-11.0.0.tgz#43e19c25dbedc8256203538e8d7e9346877a6f67" + integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== + commander@^2.12.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -3093,9 +3172,9 @@ commander@^9.2.0, commander@^9.4.0: integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== compare-versions@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-6.0.0.tgz#a3edb527e4487bfab9a8b62ffe70cebc9b87675b" - integrity sha512-s2MzYxfRsE9f/ow8hjn7ysa7pod1xhHdQMsgiJtKx6XSNf4x2N1KG4fjrkUmXcP/e9Y2ZX4zB6sHIso0Lm6evQ== + version "6.1.0" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-6.1.0.tgz#3f2131e3ae93577df111dba133e6db876ffe127a" + integrity sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg== component-emitter@^1.2.1: version "1.3.0" @@ -3193,9 +3272,9 @@ copy-descriptor@^0.1.0: integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== core-js-pure@^3.0.1: - version "3.31.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.31.1.tgz#73d154958881873bc19381df80bddb20c8d0cdb5" - integrity sha512-w+C62kvWti0EPs4KPMCMVv9DriHSXfQOCQ94bGGBiEW5rrbtt/Rz8n5Krhfw9cpFyzXBjf3DB3QnPdEzGDY4Fw== + version "3.32.0" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.32.0.tgz#5d79f85da7a4373e9a06494ccbef995a4c639f8b" + integrity sha512-qsev1H+dTNYpDUEURRuOXMvpdtAnNEvQWS/FMJ2Vb5AY8ZP4rAPQldkE27joykZPJTe0+IVgHZYh1P5Xu1/i1g== core-js@^2.4.0, core-js@^2.5.0: version "2.6.12" @@ -3679,9 +3758,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.3.47: - version "1.4.459" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.459.tgz#25a23370f4ae8aaa8f77aaf00133aa4994f4148e" - integrity sha512-XXRS5NFv8nCrBL74Rm3qhJjA2VCsRFx0OjHKBMPI0otij56aun8UWiKTDABmd5/7GTR021pA4wivs+Ri6XCElg== + version "1.4.495" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.495.tgz#d72d2eddc05d07c538275a00f2619b113848bff6" + integrity sha512-mwknuemBZnoOCths4GtpU/SDuVMp3uQHKa2UNJT9/aVD6WVRjGpXOxRGX7lm6ILIenTdGXPSTCTDaWos5tEU8Q== elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" @@ -3752,11 +3831,12 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: once "^1.4.0" enquirer@^2.3.0, enquirer@^2.3.5, enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== dependencies: ansi-colors "^4.1.1" + strip-ansi "^6.0.1" entities@^4.2.0, entities@^4.4.0: version "4.5.0" @@ -3783,11 +3863,12 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: - version "1.21.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.3.tgz#8aaa0ffc080e8a6fef6ace72631dc1ec5d47bf94" - integrity sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg== + version "1.22.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" + integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== dependencies: array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.1" available-typed-arrays "^1.0.5" call-bind "^1.0.2" es-set-tostringtag "^2.0.1" @@ -3814,10 +3895,13 @@ es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.5.0" + safe-array-concat "^1.0.0" safe-regex-test "^1.0.0" string.prototype.trim "^1.2.7" string.prototype.trimend "^1.0.6" string.prototype.trimstart "^1.0.6" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" typed-array-byte-offset "^1.0.0" typed-array-length "^1.0.4" unbox-primitive "^1.0.2" @@ -3920,9 +4004,9 @@ escodegen@1.8.x: source-map "~0.2.0" eslint-config-prettier@^8.3.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" - integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== eslint-plugin-mocha@^9.0.0: version "9.0.0" @@ -3972,9 +4056,9 @@ eslint-visitor-keys@^2.0.0: integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== eslint-visitor-keys@^3.3.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" - integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^7.32.0: version "7.32.0" @@ -4274,6 +4358,16 @@ ethereum-cryptography@^1.0.3: "@scure/bip32" "1.1.5" "@scure/bip39" "1.1.1" +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" + integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== + dependencies: + "@noble/curves" "1.1.0" + "@noble/hashes" "1.3.1" + "@scure/bip32" "1.3.1" + "@scure/bip39" "1.2.1" + ethereum-waffle@^3.2.0: version "3.4.4" resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" @@ -4732,9 +4826,9 @@ fast-diff@^1.1.2, fast-diff@^1.2.0: integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== fast-glob@^3.0.3, fast-glob@^3.2.9: - version "3.3.0" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0" - integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA== + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -5335,9 +5429,9 @@ global@~4.4.0: process "^0.11.10" globals@^13.6.0, globals@^13.9.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + version "13.21.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.21.0.tgz#163aae12f34ef502f5153cfbdd3600f36c63c571" + integrity sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg== dependencies: type-fest "^0.20.2" @@ -5450,12 +5544,12 @@ growl@1.10.5: integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" - neo-async "^2.6.0" + neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" optionalDependencies: @@ -5848,9 +5942,9 @@ immediate@~3.2.3: integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== immutable@^4.0.0-rc.12: - version "4.3.1" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.1.tgz#17988b356097ab0719e2f741d56f3ec6c317f9dc" - integrity sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A== + version "4.3.2" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.2.tgz#f89d910f8dfb6e15c03b2cae2faaf8c1f66455fe" + integrity sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" @@ -6016,10 +6110,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.11.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" - integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== dependencies: has "^1.0.3" @@ -6211,15 +6305,11 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: has-symbols "^1.0.2" is-typed-array@^1.1.10, is-typed-array@^1.1.3, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" + which-typed-array "^1.1.11" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" @@ -6504,9 +6594,9 @@ keyv@^3.0.0: json-buffer "3.0.0" keyv@^4.0.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" - integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== + version "4.5.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" + integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== dependencies: json-buffer "3.0.1" @@ -7134,6 +7224,11 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micro-ftch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" + integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== + micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -7488,7 +7583,7 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.6.0: +neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -8722,11 +8817,11 @@ resolve@1.17.0: path-parse "^1.0.6" resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.8.1, resolve@~1.22.1: - version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" - integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== dependencies: - is-core-module "^2.11.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -8926,7 +9021,7 @@ semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: +semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -9172,16 +9267,16 @@ sol2uml@2.2.0: klaw "^4.0.1" sol2uml@^2.5.4: - version "2.5.6" - resolved "https://registry.yarnpkg.com/sol2uml/-/sol2uml-2.5.6.tgz#7ab18b40dc7b8c0135ae103ec519dd616b550fc2" - integrity sha512-AN0Iu6x61L36mJWlzL3jsBQQ2VzFxdYdpcACUaoO9buM+7VuQICDBel8fG26EkW87Plqui+mxrgqfpFv/Ye2vQ== + version "2.5.12" + resolved "https://registry.yarnpkg.com/sol2uml/-/sol2uml-2.5.12.tgz#a264ab0a873d08aa9b95e46466f81457627188a3" + integrity sha512-UALaoU0XWGzCzaRr3ybyRGVUiVXJPVDLrbZa+brYb+AnZtTGk667fxSo2Qk0SAeNpsf9OHhDzTUCi+kcJTAFxA== dependencies: "@aduh95/viz.js" "^3.7.0" - "@solidity-parser/parser" "^0.15.0" + "@solidity-parser/parser" "^0.16.1" axios "^1.3.4" axios-debug-log "^1.0.0" cli-color "^2.0.3" - commander "^10.0.0" + commander "^11.0.0" convert-svg-to-png "^0.6.4" debug "^4.3.4" diff-match-patch "^1.0.5" @@ -9237,9 +9332,9 @@ solhint-plugin-prettier@^0.0.5: prettier-linter-helpers "^1.0.0" solhint@^3.2.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.4.1.tgz#8ea15b21c13d1be0b53fd46d605a24d0b36a0c46" - integrity sha512-pzZn2RlZhws1XwvLPVSsxfHrwsteFf5eySOhpAytzXwKQYbTCJV6z8EevYDiSVKMpWrvbKpEtJ055CuEmzp4Xg== + version "3.6.2" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.6.2.tgz#2b2acbec8fdc37b2c68206a71ba89c7f519943fe" + integrity sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ== dependencies: "@solidity-parser/parser" "^0.16.0" ajv "^6.12.6" @@ -9254,14 +9349,14 @@ solhint@^3.2.0: js-yaml "^4.1.0" lodash "^4.17.21" pluralize "^8.0.0" - semver "^6.3.0" + semver "^7.5.2" strip-ansi "^6.0.1" table "^6.8.1" text-table "^0.2.0" optionalDependencies: prettier "^2.8.3" -solidity-ast@^0.4.15: +solidity-ast@^0.4.26: version "0.4.49" resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.49.tgz#ecba89d10c0067845b7848c3a3e8cc61a4fc5b82" integrity sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ== @@ -10077,6 +10172,25 @@ typechain@^5.1.2: prettier "^2.1.2" ts-essentials "^7.0.1" +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + typed-array-byte-offset@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" @@ -10170,9 +10284,9 @@ underscore@1.9.1: integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== undici@^5.14.0, undici@^5.4.0: - version "5.22.1" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.22.1.tgz#877d512effef2ac8be65e695f3586922e1a57d7b" - integrity sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw== + version "5.23.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.23.0.tgz#e7bdb0ed42cebe7b7aca87ced53e6eaafb8f8ca0" + integrity sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg== dependencies: busboy "^1.6.0" @@ -10328,9 +10442,9 @@ v8-compile-cache-lib@^3.0.1: integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + version "2.4.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" + integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== validate-npm-package-license@^3.0.1: version "3.0.4" @@ -11002,7 +11116,7 @@ web3-shh@1.7.4: web3-core-subscriptions "1.7.4" web3-net "1.7.4" -web3-utils@1.10.0, web3-utils@^1.0.0-beta.31, web3-utils@^1.3.0: +web3-utils@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" integrity sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg== @@ -11042,6 +11156,20 @@ web3-utils@1.7.4: randombytes "^2.1.0" utf8 "3.0.0" +web3-utils@^1.0.0-beta.31, web3-utils@^1.3.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.1.tgz#97532130d85358628bc0ff14d94b7e9449786983" + integrity sha512-r6iUUw/uMnNcWXjhRv33Nyrhxq3VGOPBXeSzxhOXIci4SvC/LPTpROY0uTrMX7ztKyODYrHp8WhTkEf+ZnHssw== + dependencies: + "@ethereumjs/util" "^8.1.0" + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereum-cryptography "^2.1.2" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + web3@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.10.0.tgz#2fde0009f59aa756c93e07ea2a7f3ab971091274" @@ -11144,17 +11272,16 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== -which-typed-array@^1.1.10, which-typed-array@^1.1.2: - version "1.1.10" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.10.tgz#74baa2789991905c2076abb317103b866c64e69e" - integrity sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA== +which-typed-array@^1.1.10, which-typed-array@^1.1.11, which-typed-array@^1.1.2: + version "1.1.11" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== dependencies: available-typed-arrays "^1.0.5" call-bind "^1.0.2" for-each "^0.3.3" gopd "^1.0.1" has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: version "1.3.1" @@ -11183,9 +11310,9 @@ window-size@^0.2.0: integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== wordwrap@^1.0.0: version "1.0.0" From d6b7ff617d922a235ba7e7c2b565b4faa99eb64b Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Sat, 19 Aug 2023 06:43:02 +0200 Subject: [PATCH 146/163] Deploy Multicall on L3 --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 5 +++++ .../ethereum/L1AtomicTokenBridgeCreator.sol | 16 +++++++++++----- .../ethereum/L1TokenBridgeRetryableSender.sol | 8 ++++++-- .../ethereum/gateway/L1OrbitERC20Gateway.sol | 2 +- scripts/atomicTokenBridgeDeployer.ts | 12 ++++++++++-- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 0838ea148a..867f7718c9 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -56,6 +56,9 @@ contract L2AtomicTokenBridgeFactory { ); } + // deploy multicall + Create2.deploy(0, _getL2Salt(OrbitSalts.L2_MULTICALL), _creationCodeFor(l2Code.multicall)); + // transfer ownership to L2 upgradeExecutor ProxyAdmin(proxyAdmin).transferOwnership(upgradeExecutor); } @@ -294,6 +297,7 @@ struct L2RuntimeCode { bytes wethGateway; bytes aeWeth; bytes upgradeExecutor; + bytes multicall; } /** @@ -323,4 +327,5 @@ library OrbitSalts { bytes32 public constant BEACON_PROXY_FACTORY = keccak256(bytes("OrbitBeaconProxyFactory")); bytes32 public constant L2_EXECUTOR_LOGIC = keccak256(bytes("OrbitL2UpgradeExecutorLogic")); bytes32 public constant L2_EXECUTOR = keccak256(bytes("OrbitL2UpgradeExecutorProxy")); + bytes32 public constant L2_MULTICALL = keccak256(bytes("OrbitL2Multicall")); } diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 3f78bee7d3..a15fb212f5 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -17,8 +17,6 @@ import {L1WethGateway} from "./gateway/L1WethGateway.sol"; import {L1OrbitGatewayRouter} from "./gateway/L1OrbitGatewayRouter.sol"; import {L1OrbitERC20Gateway} from "./gateway/L1OrbitERC20Gateway.sol"; import {L1OrbitCustomGateway} from "./gateway/L1OrbitCustomGateway.sol"; -import {TransparentUpgradeableProxy} from - "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import { L2AtomicTokenBridgeFactory, CanonicalAddressSeed, @@ -31,12 +29,15 @@ import {IUpgradeExecutor} from "@offchainlabs/upgrade-executor/src/IUpgradeExecu import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; -import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; +import {ArbMulticall2} from "../../rpc-utils/MulticallV2.sol"; import {BeaconProxyFactory, ClonableBeaconProxy} from "../libraries/ClonableBeaconProxy.sol"; +import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; import { Initializable, OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import {TransparentUpgradeableProxy} from + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; /** * @title Layer1 token bridge creator @@ -96,6 +97,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address public l2CustomGatewayTemplate; address public l2WethGatewayTemplate; address public l2WethTemplate; + address public l2MulticallTemplate; // WETH address on L1 address public l1Weth; @@ -144,6 +146,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address _l2CustomGatewayTemplate, address _l2WethGatewayTemplate, address _l2WethTemplate, + address _l2MulticallTemplate, address _l1Weth, uint256 _gasLimitForL2FactoryDeployment ) external onlyOwner { @@ -155,6 +158,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { l2CustomGatewayTemplate = _l2CustomGatewayTemplate; l2WethGatewayTemplate = _l2WethGatewayTemplate; l2WethTemplate = _l2WethTemplate; + l2MulticallTemplate = _l2MulticallTemplate; l1Weth = _l1Weth; @@ -439,7 +443,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { l2CustomGatewayTemplate, l2WethGatewayTemplate, l2WethTemplate, - address(l1Templates.upgradeExecutor) + address(l1Templates.upgradeExecutor), + l2MulticallTemplate ), l1Addresses, getCanonicalL2StandardGatewayAddress(), @@ -473,7 +478,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { l2CustomGatewayTemplate, address(0), address(0), - address(l1Templates.upgradeExecutor) + address(l1Templates.upgradeExecutor), + l2MulticallTemplate ), l1Addresses, getCanonicalL2StandardGatewayAddress(), diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index 72b9af1f1b..8f4ddc7d69 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -57,7 +57,8 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { l2.customGatewayTemplate.code, l2.wethGatewayTemplate.code, l2.wethTemplate.code, - l2.upgradeExecutorTemplate.code + l2.upgradeExecutorTemplate.code, + l2.multicallTemplate.code ), l1.router, l1.standardGateway, @@ -104,7 +105,8 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { l2.customGatewayTemplate.code, "", "", - l2.upgradeExecutorTemplate.code + l2.upgradeExecutorTemplate.code, + l2.multicallTemplate.code ), l1.router, l1.standardGateway, @@ -181,6 +183,7 @@ struct L2TemplateAddresses { address wethGatewayTemplate; address wethTemplate; address upgradeExecutorTemplate; + address multicallTemplate; } /** @@ -207,3 +210,4 @@ interface IERC20Inbox { bytes calldata data ) external returns (uint256); } + diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index eef63c456e..70b13a3829 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -127,7 +127,7 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { /** * @notice get rollup's native token that's used to pay for fees */ - function _getNativeFeeToken() internal returns (address) { + function _getNativeFeeToken() internal view returns (address) { address bridge = address(getBridge(inbox)); return IERC20Bridge(bridge).nativeToken(); } diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index 598b04386d..cbd3feee25 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -21,6 +21,7 @@ import { IInbox__factory, IERC20Bridge__factory, IERC20__factory, + ArbMulticall2__factory, } from '../build/types' import { abi as UpgradeExecutorABI, @@ -79,6 +80,7 @@ export const createTokenBridge = async ( wethGateway: L2WethGateway__factory.bytecode, aeWeth: AeWETH__factory.bytecode, upgradeExecutor: UpgradeExecutorBytecode, + multicall: ArbMulticall2__factory.bytecode, } const gasEstimateToDeployContracts = await l2FactoryTemplate.estimateGas.deployL2Contracts( @@ -307,12 +309,12 @@ export const deployL1TokenBridgeCreator = async ( await new L1OrbitCustomGateway__factory(l1Deployer).deploy() await feeTokenBasedCustomGatewayTemplate.deployed() - const upgradeExecutor = new ethers.ContractFactory( + const upgradeExecutorFactory = new ethers.ContractFactory( UpgradeExecutorABI, UpgradeExecutorBytecode, l1Deployer ) - await upgradeExecutor.deploy() + const upgradeExecutor = await upgradeExecutorFactory.deploy() const l1Templates = { routerTemplate: routerTemplate.address, @@ -356,6 +358,11 @@ export const deployL1TokenBridgeCreator = async ( const l2WethAddressOnL1 = await new AeWETH__factory(l1Deployer).deploy() await l2WethAddressOnL1.deployed() + const l2MulticallAddressOnL1 = await new ArbMulticall2__factory( + l1Deployer + ).deploy() + await l2MulticallAddressOnL1.deployed() + //// run retryable estimate for deploying L2 factory const deployFactoryGasParams = await getEstimateForDeployingFactory( l1Deployer, @@ -371,6 +378,7 @@ export const deployL1TokenBridgeCreator = async ( l2CustomGatewayAddressOnL1.address, l2WethGatewayAddressOnL1.address, l2WethAddressOnL1.address, + l2MulticallAddressOnL1.address, l1WethAddress, deployFactoryGasParams.gasLimit ) From 30cdd755dd3fa6f43b97793000ccd79bf23a50a2 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Sat, 19 Aug 2023 08:22:46 +0200 Subject: [PATCH 147/163] Decrease contract size by not hashing the salt prefix --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 49 +++++++++---------- .../ethereum/L1AtomicTokenBridgeCreator.sol | 4 +- .../ethereum/L1TokenBridgeRetryableSender.sol | 2 - .../goerli-deployment/createTokenBridge.ts | 2 +- .../deployTokenBridgeCreator.ts | 2 +- yarn.lock | 36 +++++++------- 6 files changed, 46 insertions(+), 49 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 867f7718c9..6069f1fa76 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -256,7 +256,7 @@ contract L2AtomicTokenBridgeFactory { ); } - function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { + function _getL2Salt(bytes memory prefix) internal view returns (bytes32) { return keccak256(abi.encodePacked(prefix, msg.sender)); } @@ -304,28 +304,27 @@ struct L2RuntimeCode { * Collection of salts used in CREATE2 deployment of L2 token bridge contracts. */ library OrbitSalts { - bytes32 public constant L1_PROXY_ADMIN = keccak256(bytes("OrbitL1ProxyAdmin")); - bytes32 public constant L1_ROUTER = keccak256(bytes("OrbitL1GatewayRouterProxy")); - bytes32 public constant L1_STANDARD_GATEWAY = keccak256(bytes("OrbitL1StandardGatewayProxy")); - bytes32 public constant L1_CUSTOM_GATEWAY = keccak256(bytes("OrbitL1CustomGatewayProxy")); - bytes32 public constant L1_WETH_GATEWAY = keccak256(bytes("OrbitL1WethGatewayProxy")); - - bytes32 public constant L2_PROXY_ADMIN = keccak256(bytes("OrbitL2ProxyAdmin")); - bytes32 public constant L2_ROUTER_LOGIC = keccak256(bytes("OrbitL2GatewayRouterLogic")); - bytes32 public constant L2_ROUTER = keccak256(bytes("OrbitL2GatewayRouterProxy")); - bytes32 public constant L2_STANDARD_GATEWAY_LOGIC = - keccak256(bytes("OrbitL2StandardGatewayLogic")); - bytes32 public constant L2_STANDARD_GATEWAY = keccak256(bytes("OrbitL2StandardGatewayProxy")); - bytes32 public constant L2_CUSTOM_GATEWAY_LOGIC = keccak256(bytes("OrbitL2CustomGatewayLogic")); - bytes32 public constant L2_CUSTOM_GATEWAY = keccak256(bytes("OrbitL2CustomGatewayProxy")); - bytes32 public constant L2_WETH_GATEWAY_LOGIC = keccak256(bytes("OrbitL2WethGatewayLogic")); - bytes32 public constant L2_WETH_GATEWAY = keccak256(bytes("OrbitL2WethGatewayProxy")); - bytes32 public constant L2_WETH_LOGIC = keccak256(bytes("OrbitL2WETH")); - bytes32 public constant L2_WETH = keccak256(bytes("OrbitL2WETHProxy")); - bytes32 public constant L2_STANDARD_ERC20 = keccak256(bytes("OrbitStandardArbERC20")); - bytes32 public constant UPGRADEABLE_BEACON = keccak256(bytes("OrbitUpgradeableBeacon")); - bytes32 public constant BEACON_PROXY_FACTORY = keccak256(bytes("OrbitBeaconProxyFactory")); - bytes32 public constant L2_EXECUTOR_LOGIC = keccak256(bytes("OrbitL2UpgradeExecutorLogic")); - bytes32 public constant L2_EXECUTOR = keccak256(bytes("OrbitL2UpgradeExecutorProxy")); - bytes32 public constant L2_MULTICALL = keccak256(bytes("OrbitL2Multicall")); + bytes public constant L1_PROXY_ADMIN = bytes("OrbitL1ProxyAdmin"); + bytes public constant L1_ROUTER = bytes("OrbitL1GatewayRouterProxy"); + bytes public constant L1_STANDARD_GATEWAY = bytes("OrbitL1StandardGatewayProxy"); + bytes public constant L1_CUSTOM_GATEWAY = bytes("OrbitL1CustomGatewayProxy"); + bytes public constant L1_WETH_GATEWAY = bytes("OrbitL1WethGatewayProxy"); + + bytes public constant L2_PROXY_ADMIN = bytes("OrbitL2ProxyAdmin"); + bytes public constant L2_ROUTER_LOGIC = bytes("OrbitL2GatewayRouterLogic"); + bytes public constant L2_ROUTER = bytes("OrbitL2GatewayRouterProxy"); + bytes public constant L2_STANDARD_GATEWAY_LOGIC = bytes("OrbitL2StandardGatewayLogic"); + bytes public constant L2_STANDARD_GATEWAY = bytes("OrbitL2StandardGatewayProxy"); + bytes public constant L2_CUSTOM_GATEWAY_LOGIC = bytes("OrbitL2CustomGatewayLogic"); + bytes public constant L2_CUSTOM_GATEWAY = bytes("OrbitL2CustomGatewayProxy"); + bytes public constant L2_WETH_GATEWAY_LOGIC = bytes("OrbitL2WethGatewayLogic"); + bytes public constant L2_WETH_GATEWAY = bytes("OrbitL2WethGatewayProxy"); + bytes public constant L2_WETH_LOGIC = bytes("OrbitL2WETH"); + bytes public constant L2_WETH = bytes("OrbitL2WETHProxy"); + bytes public constant L2_STANDARD_ERC20 = bytes("OrbitStandardArbERC20"); + bytes public constant UPGRADEABLE_BEACON = bytes("OrbitUpgradeableBeacon"); + bytes public constant BEACON_PROXY_FACTORY = bytes("OrbitBeaconProxyFactory"); + bytes public constant L2_EXECUTOR_LOGIC = bytes("OrbitL2UpgradeExecutorLogic"); + bytes public constant L2_EXECUTOR = bytes("OrbitL2UpgradeExecutorProxy"); + bytes public constant L2_MULTICALL = bytes("OrbitL2Multicall"); } diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index a15fb212f5..8da5117810 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -686,11 +686,11 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return IInbox(inbox).bridge().rollup().owner(); } - function _getL1Salt(bytes32 prefix, address inbox) internal pure returns (bytes32) { + function _getL1Salt(bytes memory prefix, address inbox) internal pure returns (bytes32) { return keccak256(abi.encodePacked(prefix, inbox)); } - function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { + function _getL2Salt(bytes memory prefix) internal view returns (bytes32) { return keccak256( abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(retryableSender))) ); diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index 8f4ddc7d69..1a16f24af0 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -5,7 +5,6 @@ import {IInbox} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import { L2AtomicTokenBridgeFactory, L2RuntimeCode, - OrbitSalts, ProxyAdmin } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import { @@ -210,4 +209,3 @@ interface IERC20Inbox { bytes calldata data ) external returns (uint256); } - diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts index 016c4e233f..c802a6d752 100644 --- a/scripts/goerli-deployment/createTokenBridge.ts +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -14,7 +14,7 @@ export const envVars = { childChainRpc: process.env['ORBIT_RPC'] as string, } -const L1_TOKEN_BRIDGE_CREATOR = '0xc9CDf2425961e232FdBA51650A729710de7bfa69' +const L1_TOKEN_BRIDGE_CREATOR = '0xce1CAd780c529e66e3aa6D952a1ED9A6447791c1' /** * Steps: diff --git a/scripts/goerli-deployment/deployTokenBridgeCreator.ts b/scripts/goerli-deployment/deployTokenBridgeCreator.ts index 19048cbd0c..5390628f1f 100644 --- a/scripts/goerli-deployment/deployTokenBridgeCreator.ts +++ b/scripts/goerli-deployment/deployTokenBridgeCreator.ts @@ -127,7 +127,7 @@ const registerGoerliNetworks = async ( async function main() { // this is just random Orbit rollup that will be used to estimate gas needed to deploy L2 token bridge factory via retryable - const rollupAddress = '0xDAB64b6E86035Aa9EB697341B663fb4B46930E60' + const rollupAddress = '0x3c8045E038d9Ce79D2D05cB75B223dbDDF97403B' const l1TokenBridgeCreator = await deployTokenBridgeCreator(rollupAddress) console.log('L1TokenBridgeCreator:', l1TokenBridgeCreator.address) } diff --git a/yarn.lock b/yarn.lock index 173faa53e8..3dfe350a26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,9 +24,9 @@ sol2uml "2.2.0" "@arbitrum/sdk@^3.1.5": - version "3.1.7" - resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.7.tgz#a543ec105cff68c05165fd5af377fb9f14282b98" - integrity sha512-ITuVvNPpvjlgEk8CKgexkfkEtKvL1eRZUTgqavenjOS8egZuklMoyDnJ08yG4KU+cOQW11dv2eepWDcvbR/NmQ== + version "3.1.8" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.8.tgz#6100e0197954b59e1f8f48df46080df9a1d8284c" + integrity sha512-X2eur5Y7QDFxjmzmXY3YhSujXd5Lncjvk/VVjvpNIjNTp8FVGilQ1jEV7N9Jr3+5/Ca3uvw6+Q6x/6KMKeGMGA== dependencies: "@ethersproject/address" "^5.0.8" "@ethersproject/bignumber" "^5.1.1" @@ -1177,9 +1177,9 @@ form-data "^3.0.0" "@types/node@*": - version "20.5.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.0.tgz#7fc8636d5f1aaa3b21e6245e97d56b7f56702313" - integrity sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q== + version "20.5.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.1.tgz#178d58ee7e4834152b0e8b4d30cbfab578b9bb30" + integrity sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg== "@types/node@^10.0.3": version "10.17.60" @@ -3272,9 +3272,9 @@ copy-descriptor@^0.1.0: integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== core-js-pure@^3.0.1: - version "3.32.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.32.0.tgz#5d79f85da7a4373e9a06494ccbef995a4c639f8b" - integrity sha512-qsev1H+dTNYpDUEURRuOXMvpdtAnNEvQWS/FMJ2Vb5AY8ZP4rAPQldkE27joykZPJTe0+IVgHZYh1P5Xu1/i1g== + version "3.32.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.32.1.tgz#5775b88f9062885f67b6d7edce59984e89d276f3" + integrity sha512-f52QZwkFVDPf7UEQZGHKx6NYxsxmVGJe5DIvbzOdRMJlmT6yv0KDjR8rmy3ngr/t5wU54c7Sp/qIJH0ppbhVpQ== core-js@^2.4.0, core-js@^2.5.0: version "2.6.12" @@ -3758,9 +3758,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.3.47: - version "1.4.495" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.495.tgz#d72d2eddc05d07c538275a00f2619b113848bff6" - integrity sha512-mwknuemBZnoOCths4GtpU/SDuVMp3uQHKa2UNJT9/aVD6WVRjGpXOxRGX7lm6ILIenTdGXPSTCTDaWos5tEU8Q== + version "1.4.496" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.496.tgz#a57534b70d2bdee7e1ad7dbd4c91e560cbd08db1" + integrity sha512-qeXC3Zbykq44RCrBa4kr8v/dWzYJA8rAwpyh9Qd+NKWoJfjG5vvJqy9XOJ9H4P/lqulZBCgUWAYi+FeK5AuJ8g== elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" @@ -7626,9 +7626,9 @@ node-fetch@2.6.7: whatwg-url "^5.0.0" node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: - version "2.6.12" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" - integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + version "2.6.13" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.13.tgz#a20acbbec73c2e09f9007de5cda17104122e0010" + integrity sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA== dependencies: whatwg-url "^5.0.0" @@ -9267,9 +9267,9 @@ sol2uml@2.2.0: klaw "^4.0.1" sol2uml@^2.5.4: - version "2.5.12" - resolved "https://registry.yarnpkg.com/sol2uml/-/sol2uml-2.5.12.tgz#a264ab0a873d08aa9b95e46466f81457627188a3" - integrity sha512-UALaoU0XWGzCzaRr3ybyRGVUiVXJPVDLrbZa+brYb+AnZtTGk667fxSo2Qk0SAeNpsf9OHhDzTUCi+kcJTAFxA== + version "2.5.13" + resolved "https://registry.yarnpkg.com/sol2uml/-/sol2uml-2.5.13.tgz#095f34e7ab0e7e62e0680b7eb2dcb32bcf408bc7" + integrity sha512-ACfGQzfciKuCZw7//P2URj1bRHoX/KnJweuPKNcctzalSZGsjNdw8uRzLl1ph00F9xqu4z9wpDGWJ0GSzox2SQ== dependencies: "@aduh95/viz.js" "^3.7.0" "@solidity-parser/parser" "^0.16.1" From eeac040aeb093624dd4926d19c8611a64f58d53f Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 25 Aug 2023 16:07:11 +0200 Subject: [PATCH 148/163] Prepare crosschain hardhat tests for CI --- lib/nitro-contracts | 2 +- package.json | 1 - .../deployCreatorAndCreateTokenBridge.ts | 54 ++++--- scripts/local-deployment/testSetup.ts | 149 ------------------ test-e2e/orbitTokenBridge.ts | 48 +++--- 5 files changed, 61 insertions(+), 193 deletions(-) delete mode 100644 scripts/local-deployment/testSetup.ts diff --git a/lib/nitro-contracts b/lib/nitro-contracts index a182f842f1..570e8180ad 160000 --- a/lib/nitro-contracts +++ b/lib/nitro-contracts @@ -1 +1 @@ -Subproject commit a182f842f13f437040dcadfcb6741f20ea929272 +Subproject commit 570e8180ade4e89b9a2e369afe4fa61f09d35fb6 diff --git a/package.json b/package.json index 5edc0b423d..6d537319a9 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ ], "dependencies": { "@arbitrum/nitro-contracts": "^1.0.0-beta.8", - "@arbitrum/sdk": "^3.1.5", "@openzeppelin/contracts": "4.8.3", "@openzeppelin/contracts-upgradeable": "4.8.3" }, diff --git a/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts b/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts index 803fe30a9b..41af973f43 100644 --- a/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts +++ b/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts @@ -9,6 +9,7 @@ import { createTokenBridge, deployL1TokenBridgeCreator, } from '../atomicTokenBridgeDeployer' +import { l2Networks } from '@arbitrum/sdk/dist/lib/dataEntities/networks' /** * Steps: @@ -44,29 +45,32 @@ export const setupTokenBridgeInLocalEnv = async () => { ) // register - needed for retryables - addCustomNetwork({ - customL1Network: l1Network, - customL2Network: { - ...coreL2Network, - tokenBridge: { - l1CustomGateway: '', - l1ERC20Gateway: '', - l1GatewayRouter: '', - l1MultiCall: '', - l1ProxyAdmin: '', - l1Weth: '', - l1WethGateway: '', - - l2CustomGateway: '', - l2ERC20Gateway: '', - l2GatewayRouter: '', - l2Multicall: '', - l2ProxyAdmin: '', - l2Weth: '', - l2WethGateway: '', + 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: '', + }, }, - }, - }) + }) + } // prerequisite - deploy L1 creator and set templates const l1Weth = ethers.Wallet.createRandom().address @@ -109,6 +113,7 @@ export const setupTokenBridgeInLocalEnv = async () => { return { l1Network, l2Network, + l1TokenBridgeCreator, } } @@ -192,12 +197,13 @@ export const getLocalNetworks = async ( } async function main() { - const { l1Network, l2Network } = await setupTokenBridgeInLocalEnv() + const { l1Network, l2Network, l1TokenBridgeCreator } = + await setupTokenBridgeInLocalEnv() const NETWORK_FILE = 'network.json' fs.writeFileSync( NETWORK_FILE, - JSON.stringify({ l1Network, l2Network }, null, 2) + JSON.stringify({ l1Network, l2Network, l1TokenBridgeCreator }, null, 2) ) console.log(NETWORK_FILE + ' updated') } diff --git a/scripts/local-deployment/testSetup.ts b/scripts/local-deployment/testSetup.ts deleted file mode 100644 index 18e6774ed0..0000000000 --- a/scripts/local-deployment/testSetup.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { JsonRpcProvider } from '@ethersproject/providers' -import { L1Network, L2Network, addCustomNetwork } from '@arbitrum/sdk' -import { execSync } from 'child_process' -import { Bridge__factory } from '@arbitrum/sdk/dist/lib/abi/factories/Bridge__factory' -import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' -import { Signer, Wallet } from 'ethers' -import { deployOrbitTokenBridgeAndInit } from './orbitTokenBridgeDeployer' - -export const getCustomNetworks = async ( - l1Url: string, - l2Url: string -): Promise<{ - l1Network: L1Network - l2Network: Omit & { nativeToken: string } -}> => { - const l1Provider = new JsonRpcProvider(l1Url) - const l2Provider = new JsonRpcProvider(l2Url) - let deploymentData: string - try { - deploymentData = execSync( - 'docker exec nitro_sequencer_1 cat /config/deployment.json' - ).toString() - } catch (e) { - deploymentData = execSync( - 'docker exec nitro-sequencer-1 cat /config/deployment.json' - ).toString() - } - const parsedDeploymentData = JSON.parse(deploymentData) as { - bridge: string - inbox: string - ['sequencer-inbox']: string - rollup: string - ['native-erc20-token']: string - } - - const rollup = RollupAdminLogic__factory.connect( - parsedDeploymentData.rollup, - l1Provider - ) - const confirmPeriodBlocks = await rollup.confirmPeriodBlocks() - - const bridge = Bridge__factory.connect( - parsedDeploymentData.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 & { nativeToken: string } = { - chainID: l2NetworkInfo.chainId, - confirmPeriodBlocks: confirmPeriodBlocks.toNumber(), - ethBridge: { - bridge: parsedDeploymentData.bridge, - inbox: parsedDeploymentData.inbox, - outbox: outboxAddr, - rollup: parsedDeploymentData.rollup, - sequencerInbox: parsedDeploymentData['sequencer-inbox'], - }, - nativeToken: parsedDeploymentData['native-erc20-token'], - explorerUrl: '', - isArbitrum: true, - isCustom: true, - name: 'ArbLocal', - partnerChainID: l1NetworkInfo.chainId, - retryableLifetimeSeconds: 7 * 24 * 60 * 60, - nitroGenesisBlock: 0, - nitroGenesisL1Block: 0, - depositTimeout: 900000, - } - return { - l1Network, - l2Network, - } -} - -export const setupOrbitTokenBridge = async ( - l1Deployer: Signer, - l2Deployer: Signer, - l1Url: string, - l2Url: string -) => { - const { l1Network, l2Network: coreL2Network } = await getCustomNetworks( - l1Url, - l2Url - ) - - const { l1: l1Contracts, l2: l2Contracts } = - await deployOrbitTokenBridgeAndInit( - l1Deployer, - l2Deployer, - coreL2Network.ethBridge.inbox, - coreL2Network.nativeToken - ) - const l2Network: L2Network & { - nativeToken: string - } = { - ...coreL2Network, - tokenBridge: { - l1CustomGateway: l1Contracts.customGateway.address, - l1ERC20Gateway: l1Contracts.standardGateway.address, - l1GatewayRouter: l1Contracts.router.address, - l1MultiCall: '', - l1ProxyAdmin: l1Contracts.proxyAdmin.address, - l1Weth: '', - l1WethGateway: '', - - l2CustomGateway: l2Contracts.customGateway.address, - l2ERC20Gateway: l2Contracts.standardGateway.address, - l2GatewayRouter: l2Contracts.router.address, - l2Multicall: '', - l2ProxyAdmin: l2Contracts.proxyAdmin.address, - l2Weth: '', - l2WethGateway: '', - }, - } - - addCustomNetwork({ - customL1Network: l1Network, - customL2Network: l2Network, - }) - - return { - l1Network, - l2Network, - } -} - -export const getSigner = (provider: JsonRpcProvider, key?: string) => { - if (!key && !provider) - throw new Error('Provide at least one of key or provider.') - if (key) return new Wallet(key).connect(provider) - else return provider.getSigner(0) -} - -export function sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)) -} diff --git a/test-e2e/orbitTokenBridge.ts b/test-e2e/orbitTokenBridge.ts index 08b64579ef..7dcf601d15 100644 --- a/test-e2e/orbitTokenBridge.ts +++ b/test-e2e/orbitTokenBridge.ts @@ -9,14 +9,13 @@ import { import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' import { JsonRpcProvider } from '@ethersproject/providers' import { expect } from 'chai' -import { ethers, Wallet } from '@arbitrum/sdk/node_modules/ethers' -import { - setupOrbitTokenBridge, - sleep, -} from '../scripts/local-deployment/testSetup' +// import { ethers, Wallet } from '@arbitrum/sdk/node_modules/ethers' +import { setupTokenBridgeInLocalEnv } from '../scripts/local-deployment/deployCreatorAndCreateTokenBridge' import { ERC20, ERC20__factory, + IERC20Bridge__factory, + IInbox__factory, L1OrbitERC20Gateway__factory, L1OrbitGatewayRouter__factory, L2GatewayRouter__factory, @@ -24,8 +23,7 @@ import { TestERC20__factory, } from '../build/types' import { defaultAbiCoder } from 'ethers/lib/utils' -import { BigNumber } from 'ethers' -import { IERC20Inbox__factory } from '../build/types' +import { BigNumber, Wallet, ethers } from 'ethers' const config = { arbUrl: 'http://localhost:8547', @@ -42,7 +40,7 @@ let userL1Wallet: Wallet let userL2Wallet: Wallet let _l1Network: L1Network -let _l2Network: L2Network & { nativeToken: string } +let _l2Network: L2Network let token: TestERC20 let l2Token: ERC20 @@ -61,12 +59,7 @@ describe('orbitTokenBridge', () => { deployerL2Wallet = new ethers.Wallet(deployerKey, l2Provider) console.log('setupOrbitTokenBridge') - const { l1Network, l2Network } = await setupOrbitTokenBridge( - deployerL1Wallet, - deployerL2Wallet, - config.ethUrl, - config.arbUrl - ) + const { l1Network, l2Network } = await setupTokenBridgeInLocalEnv() _l1Network = l1Network _l2Network = l2Network @@ -93,14 +86,14 @@ describe('orbitTokenBridge', () => { expect((await l1Router.defaultGateway()).toLowerCase()).to.be.eq( _l2Network.tokenBridge.l1ERC20Gateway.toLowerCase() ) - // expect((await l1Router.counterpartGateway()).toLowerCase()).to.be.eq( - // _l2Network.tokenBridge.l2ERC20Gateway.toLowerCase() - // ) }) it('can deposit token via default gateway', async function () { // fund user to be able to pay retryable fees - nativeToken = ERC20__factory.connect(_l2Network.nativeToken, userL1Wallet) + nativeToken = ERC20__factory.connect( + await getFeeToken(_l2Network.ethBridge.inbox, userL1Wallet), + userL1Wallet + ) await ( await nativeToken .connect(deployerL1Wallet) @@ -344,3 +337,22 @@ async function waitOnL2Msg(tx: ethers.ContractTransaction) { const status = messageResult.status expect(status).to.be.eq(L1ToL2MessageStatus.REDEEMED) } + +const getFeeToken = async (inbox: string, l1Provider: any) => { + const bridge = await IInbox__factory.connect(inbox, l1Provider).bridge() + + let feeToken = ethers.constants.AddressZero + + try { + feeToken = await IERC20Bridge__factory.connect( + bridge, + l1Provider + ).nativeToken() + } catch {} + + return feeToken +} + +function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)) +} From d8030530da53dcfdb1aba2b47a3af69646f297c0 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 25 Aug 2023 16:15:24 +0200 Subject: [PATCH 149/163] Add comments --- .../ethereum/gateway/L1ArbitrumGateway.sol | 3 +- .../ethereum/gateway/L1OrbitERC20Gateway.sol | 2 + .../gateway/L1OrbitReverseCustomGateway.sol | 2 +- lib/nitro-contracts | 2 +- yarn.lock | 402 ++++++++++++------ 5 files changed, 273 insertions(+), 138 deletions(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol index 345fea8a2f..8ac88717a4 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1ArbitrumGateway.sol @@ -377,7 +377,6 @@ abstract contract L1ArbitrumGateway is * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution * @param _gasPriceBid Gas price for L2 execution * @param _maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee - * //param tokenTotalFeeAmount Amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups) * @param _data encoded data from router and user * @return res abi encoded inbox sequence number */ @@ -388,7 +387,7 @@ abstract contract L1ArbitrumGateway is uint256 _maxGas, uint256 _gasPriceBid, uint256 _maxSubmissionCost, - uint256, // tokenTotalFeeAmount + uint256, // tokenTotalFeeAmount - amount of fees to be deposited in native token to cover for retryable ticket cost (used only in ERC20-based rollups) bytes memory _data ) internal virtual returns (uint256) { return diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index eef63c456e..dd18aa4cbb 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -25,6 +25,8 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { uint256 _gasPriceBid, bytes calldata _data ) public payable override returns (bytes memory res) { + // We don't allow bridging of native token to avoid having multiple representations of it + // on child chain. Native token can be bridged directly through inbox using depositERC20(). require(_l1Token != _getNativeFeeToken(), "NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); return diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol index f875946c3c..da07bb5dd7 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitReverseCustomGateway.sol @@ -13,7 +13,7 @@ import { IArbToken } from "../../arbitrum/IArbToken.sol"; * rather than the L1. * @dev The reverse custom gateway burns on the l2 and escrows on the l1 * which is the opposite of the way the normal custom gateway works - * This means that the total supply L2 isn't affected by briding, which + * This means that the total supply L2 isn't affected by bridging, which * is helpful for observers calculating the total supply especially if * if minting is also occuring on L2 */ diff --git a/lib/nitro-contracts b/lib/nitro-contracts index a182f842f1..d5d33c2b8d 160000 --- a/lib/nitro-contracts +++ b/lib/nitro-contracts @@ -1 +1 @@ -Subproject commit a182f842f13f437040dcadfcb6741f20ea929272 +Subproject commit d5d33c2b8d5615563b8c553ca2a1bb936c039924 diff --git a/yarn.lock b/yarn.lock index a8e1cf4d80..b1b21f7d5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,9 +24,9 @@ sol2uml "2.2.0" "@arbitrum/sdk@^3.1.5": - version "3.1.6" - resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.6.tgz#0a64728040bd1ca4d6d8024946991308d248f303" - integrity sha512-wY7RHmvY26yc/OuwpJY+kjgAmUJZDGDXaQxfSQTp2t6sSFO+8oFFVsKIthBCY2RpDGFUVTGpRjCUEXiuJ6/SFA== + version "3.1.9" + resolved "https://registry.yarnpkg.com/@arbitrum/sdk/-/sdk-3.1.9.tgz#a511bc70cdd0a947445e4e27833c242ccb77ddf5" + integrity sha512-7Rf75cKmQ8nutTV+2JAOXcI6DKG4D7QCJz1JL2nq6hUpRuw4jyKn+irLqJtcIExssylLWt3t/pKV6fYseCYKNg== dependencies: "@ethersproject/address" "^5.0.8" "@ethersproject/bignumber" "^5.1.1" @@ -41,24 +41,25 @@ "@babel/highlight" "^7.10.4" "@babel/code-frame@^7.0.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" - integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ== + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.10.tgz#1c20e612b768fefa75f6e90d6ecb86329247f0a3" + integrity sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA== dependencies: - "@babel/highlight" "^7.22.5" + "@babel/highlight" "^7.22.10" + chalk "^2.4.2" "@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== -"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031" - integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw== +"@babel/highlight@^7.10.4", "@babel/highlight@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7" + integrity sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ== dependencies: "@babel/helper-validator-identifier" "^7.22.5" - chalk "^2.0.0" + chalk "^2.4.2" js-tokens "^4.0.0" "@colors/colors@1.5.0": @@ -215,6 +216,11 @@ ethereumjs-util "^7.1.1" miller-rabin "^4.0.0" +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + "@ethereumjs/tx@3.3.2": version "3.3.2" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.3.2.tgz#348d4624bf248aaab6c44fec2ae67265efe3db00" @@ -231,6 +237,15 @@ "@ethereumjs/common" "^2.6.4" ethereumjs-util "^7.1.5" +"@ethereumjs/util@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" + integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" + "@ethereumjs/vm@^5.9.0": version "5.9.3" resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.9.3.tgz#6d69202e4c132a4a1e1628ac246e92062e230823" @@ -649,11 +664,28 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" +"@noble/curves@1.1.0", "@noble/curves@~1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" + integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== + dependencies: + "@noble/hashes" "1.3.1" + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== +"@noble/hashes@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + "@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": version "1.7.1" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" @@ -727,18 +759,18 @@ integrity sha512-bQHV8R9Me8IaJoJ2vPG4rXcL7seB7YVuskr4f+f5RyOStSZetwzkWtoqDMl5erkBJy0lDRUnIR2WIkPiC0GJlg== "@openzeppelin/upgrades-core@^1.24.1": - version "1.27.3" - resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.27.3.tgz#d5578e3a3ccd18a61fc585945be67951480238b5" - integrity sha512-IqlSMUkno1XKF4L46aUqZ4BqHxj4dF0BRGrFcKeG2Q0vrsKoazhY67JG9bO+wMYG4zxl6jgmG0bd5ef9HLcLmw== + version "1.28.0" + resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.28.0.tgz#19405f272dc09e766c756d9d149cbd680168aef7" + integrity sha512-8RKlyg98Adv+46GxDaR0awL3R8bVCcQ27DcSEwrgWOp6siHh8sZg4a2l+2dhPl1510S6uBfhHSydMH5VX2BV5g== dependencies: - cbor "^8.0.0" + cbor "^9.0.0" chalk "^4.1.0" compare-versions "^6.0.0" debug "^4.1.1" ethereumjs-util "^7.0.3" minimist "^1.2.7" proper-lockfile "^4.1.1" - solidity-ast "^0.4.15" + solidity-ast "^0.4.26" "@resolver-engine/core@^0.3.3": version "0.3.3" @@ -791,6 +823,15 @@ "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" +"@scure/bip32@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" + integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== + dependencies: + "@noble/curves" "~1.1.0" + "@noble/hashes" "~1.3.1" + "@scure/base" "~1.1.0" + "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.1.1.tgz#b54557b2e86214319405db819c4b6a370cf340c5" @@ -799,6 +840,14 @@ "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" @@ -891,14 +940,7 @@ dependencies: antlr4ts "^0.5.0-alpha.4" -"@solidity-parser/parser@^0.15.0": - version "0.15.0" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.15.0.tgz#1d359be40be84f174dd616ccfadcf43346c6bf63" - integrity sha512-5UFJJTzWi1hgFk6aGCZ5rxG2DJkCJOzJ74qg7UkWSNCDSigW+CJLoYUb5bLiKrtI34Nr9rpFSUNHfkqtlL+N/w== - dependencies: - antlr4ts "^0.5.0-alpha.4" - -"@solidity-parser/parser@^0.16.0": +"@solidity-parser/parser@^0.16.0", "@solidity-parser/parser@^0.16.1": version "0.16.1" resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.16.1.tgz#f7c8a686974e1536da0105466c4db6727311253c" integrity sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw== @@ -932,9 +974,9 @@ integrity sha512-sE7c9IHIGdbK4YayH4BC8i8qMjoAOeg6nUXUDZZp8wlU21/EMpaG+CLx+KqcIPyR+GSWIW3Dm0PXkr2nlggFDA== "@truffle/interface-adapter@^0.5.25": - version "0.5.34" - resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.34.tgz#a45edc23d6ace0e01ebf237b668119f456729643" - integrity sha512-gPxabfMi2TueE4VxnNuyeudOfvGJQ1ofVC02PFw14cnRQhzH327JikjjQbZ1bT6S7kWl9H6P3hQPFeYFMHdm1g== + version "0.5.35" + resolved "https://registry.yarnpkg.com/@truffle/interface-adapter/-/interface-adapter-0.5.35.tgz#f0eb1c4a2803190ca249143f545029a8b641fe96" + integrity sha512-B5gtJnvsum5j2do393n0UfCT8MklrlAZxuqvEFBeMM9UKnreYct0/D368FVMlZwWo1N50HgGeZ0hlpSJqR/nvg== dependencies: bn.js "^5.1.3" ethers "^4.0.32" @@ -993,9 +1035,9 @@ fs-extra "^9.1.0" "@types/abstract-leveldown@*": - version "7.2.1" - resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.1.tgz#bb16403c17754b0c4d5772d71d03b924a03d4c80" - integrity sha512-YK8irIC+eMrrmtGx0H4ISn9GgzLd9dojZWJaMbjp1YHLl2VqqNFBNrL5Q3KjGf4VE3sf/4hmq6EhQZ7kZp1NoQ== + version "7.2.2" + resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.2.tgz#45fed99f966749a6fc351131465026584e99456b" + integrity sha512-EVVYLp4D3zwP5/sS2S5x70t1w0BDrjbv0x0d0znngFKX/YExe+il/JAlHOEpo0cTdtY4Ohnllen32hPganG20w== "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": version "4.11.6" @@ -1122,9 +1164,9 @@ form-data "^3.0.0" "@types/node@*": - version "20.4.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.2.tgz#129cc9ae69f93824f92fac653eebfb4812ab4af9" - integrity sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw== + version "20.5.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.5.6.tgz#5e9aaa86be03a09decafd61b128d6cec64a5fe40" + integrity sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ== "@types/node@^10.0.3": version "10.17.60" @@ -1137,9 +1179,9 @@ integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== "@types/node@^14.14.28": - version "14.18.53" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.53.tgz#42855629b8773535ab868238718745bf56c56219" - integrity sha512-soGmOpVBUq+gaBMwom1M+krC/NNbWlosh4AtGA03SyWNDiqSKtwp7OulO1M6+mg8YkHMvJ/y0AkCeO8d1hNb7A== + version "14.18.56" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.56.tgz#09e092d684cd8cfbdb3c5e5802672712242f2600" + integrity sha512-+k+57NVS9opgrEn5l9c0gvD1r6C+PtyhVE4BTnMMRwiEA8ZO8uFcs6Yy2sXIy0eC95ZurBtRSvhZiHXBysbl6w== "@types/node@^8.0.0": version "8.10.66" @@ -1659,6 +1701,17 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== +array.prototype.findlast@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.2.tgz#134ef6b7215f131a8884fafe6af46846a032c518" + integrity sha512-p1YDNPNqA+P6cPX9ATsxg7DKir7gOmJ+jh5dEP3LlumMNYVC1F2Jgnyh6oI3n/qD9FeIkqR2jXfd73G68ImYUQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.1.3" + array.prototype.reduce@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac" @@ -1670,6 +1723,18 @@ array.prototype.reduce@^1.0.5: es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" +arraybuffer.prototype.slice@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb" + integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -2762,26 +2827,33 @@ camelcase@^6.0.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30000844: - version "1.0.30001515" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001515.tgz#418aefeed9d024cd3129bfae0ccc782d4cb8f12b" - integrity sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA== + version "1.0.30001523" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001523.tgz#b838f70b1a98c556776b998fafb47d2b64146d4f" + integrity sha512-I5q5cisATTPZ1mc588Z//pj/Ox80ERYDfR71YnvY7raS/NOk8xXlZcB0sF7JdqaV//kOaa6aus7lRfpdnt1eBA== caseless@^0.12.0, caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -cbor@^8.0.0, cbor@^8.1.0: +cbor@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5" integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg== dependencies: nofilter "^3.1.0" +cbor@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-9.0.1.tgz#b16e393d4948d44758cd54ac6151379d443b37ae" + integrity sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ== + dependencies: + nofilter "^3.1.0" + chai@^4.2.0: - version "4.3.7" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" - integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + version "4.3.8" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.8.tgz#40c59718ad6928da6629c70496fe990b2bb5b17c" + integrity sha512-vX4YvVVtxlfSZ2VecZgFUTU5qPCYsobVI2O9FmwEXBhDigYGQA6jRXCycIs1yJnnWbZ6/+a2zNIF5DfVCcJBFQ== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" @@ -2802,7 +2874,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3082,6 +3154,11 @@ commander@^10.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +commander@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-11.0.0.tgz#43e19c25dbedc8256203538e8d7e9346877a6f67" + integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== + commander@^2.12.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -3093,9 +3170,9 @@ commander@^9.2.0, commander@^9.4.0: integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== compare-versions@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-6.0.0.tgz#a3edb527e4487bfab9a8b62ffe70cebc9b87675b" - integrity sha512-s2MzYxfRsE9f/ow8hjn7ysa7pod1xhHdQMsgiJtKx6XSNf4x2N1KG4fjrkUmXcP/e9Y2ZX4zB6sHIso0Lm6evQ== + version "6.1.0" + resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-6.1.0.tgz#3f2131e3ae93577df111dba133e6db876ffe127a" + integrity sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg== component-emitter@^1.2.1: version "1.3.0" @@ -3193,9 +3270,9 @@ copy-descriptor@^0.1.0: integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== core-js-pure@^3.0.1: - version "3.31.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.31.1.tgz#73d154958881873bc19381df80bddb20c8d0cdb5" - integrity sha512-w+C62kvWti0EPs4KPMCMVv9DriHSXfQOCQ94bGGBiEW5rrbtt/Rz8n5Krhfw9cpFyzXBjf3DB3QnPdEzGDY4Fw== + version "3.32.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.32.1.tgz#5775b88f9062885f67b6d7edce59984e89d276f3" + integrity sha512-f52QZwkFVDPf7UEQZGHKx6NYxsxmVGJe5DIvbzOdRMJlmT6yv0KDjR8rmy3ngr/t5wU54c7Sp/qIJH0ppbhVpQ== core-js@^2.4.0, core-js@^2.5.0: version "2.6.12" @@ -3679,9 +3756,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.3.47: - version "1.4.459" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.459.tgz#25a23370f4ae8aaa8f77aaf00133aa4994f4148e" - integrity sha512-XXRS5NFv8nCrBL74Rm3qhJjA2VCsRFx0OjHKBMPI0otij56aun8UWiKTDABmd5/7GTR021pA4wivs+Ri6XCElg== + version "1.4.502" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.502.tgz#531cda8774813d97d6cfa2fb9d8ee3e2c75851fa" + integrity sha512-xqeGw3Gr6o3uyHy/yKjdnDQHY2RQvXcGC2cfHjccK1IGkH6cX1WQBN8EeC/YpwPhGkBaikDTecJ8+ssxSVRQlw== elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" @@ -3752,11 +3829,12 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: once "^1.4.0" enquirer@^2.3.0, enquirer@^2.3.5, enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + version "2.4.1" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" + integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== dependencies: ansi-colors "^4.1.1" + strip-ansi "^6.0.1" entities@^4.2.0, entities@^4.4.0: version "4.5.0" @@ -3783,11 +3861,12 @@ error-ex@^1.2.0, error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: - version "1.21.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.3.tgz#8aaa0ffc080e8a6fef6ace72631dc1ec5d47bf94" - integrity sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg== + version "1.22.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc" + integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw== dependencies: array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.1" available-typed-arrays "^1.0.5" call-bind "^1.0.2" es-set-tostringtag "^2.0.1" @@ -3814,10 +3893,13 @@ es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2: object-keys "^1.1.1" object.assign "^4.1.4" regexp.prototype.flags "^1.5.0" + safe-array-concat "^1.0.0" safe-regex-test "^1.0.0" string.prototype.trim "^1.2.7" string.prototype.trimend "^1.0.6" string.prototype.trimstart "^1.0.6" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" typed-array-byte-offset "^1.0.0" typed-array-length "^1.0.4" unbox-primitive "^1.0.2" @@ -3837,6 +3919,13 @@ es-set-tostringtag@^2.0.1: has "^1.0.3" has-tostringtag "^1.0.0" +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -3920,9 +4009,9 @@ escodegen@1.8.x: source-map "~0.2.0" eslint-config-prettier@^8.3.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" - integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== eslint-plugin-mocha@^9.0.0: version "9.0.0" @@ -3972,9 +4061,9 @@ eslint-visitor-keys@^2.0.0: integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== eslint-visitor-keys@^3.3.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" - integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^7.32.0: version "7.32.0" @@ -4274,6 +4363,16 @@ ethereum-cryptography@^1.0.3: "@scure/bip32" "1.1.5" "@scure/bip39" "1.1.1" +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" + integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== + dependencies: + "@noble/curves" "1.1.0" + "@noble/hashes" "1.3.1" + "@scure/bip32" "1.3.1" + "@scure/bip39" "1.2.1" + ethereum-waffle@^3.2.0: version "3.4.4" resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.4.tgz#1378b72040697857b7f5e8f473ca8f97a37b5840" @@ -4732,9 +4831,9 @@ fast-diff@^1.1.2, fast-diff@^1.2.0: integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== fast-glob@^3.0.3, fast-glob@^3.2.9: - version "3.3.0" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.0.tgz#7c40cb491e1e2ed5664749e87bfb516dbe8727c0" - integrity sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA== + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -5088,9 +5187,9 @@ fsevents@~2.1.1: integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== function-bind@^1.1.1: version "1.1.1" @@ -5335,9 +5434,9 @@ global@~4.4.0: process "^0.11.10" globals@^13.6.0, globals@^13.9.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + version "13.21.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.21.0.tgz#163aae12f34ef502f5153cfbdd3600f36c63c571" + integrity sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg== dependencies: type-fest "^0.20.2" @@ -5450,12 +5549,12 @@ growl@1.10.5: integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== dependencies: minimist "^1.2.5" - neo-async "^2.6.0" + neo-async "^2.6.2" source-map "^0.6.1" wordwrap "^1.0.0" optionalDependencies: @@ -5848,9 +5947,9 @@ immediate@~3.2.3: integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== immutable@^4.0.0-rc.12: - version "4.3.1" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.1.tgz#17988b356097ab0719e2f741d56f3ec6c317f9dc" - integrity sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A== + version "4.3.4" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f" + integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" @@ -6016,10 +6115,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.11.0: - version "2.12.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" - integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== +is-core-module@^2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" + integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== dependencies: has "^1.0.3" @@ -6211,15 +6310,11 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: has-symbols "^1.0.2" is-typed-array@^1.1.10, is-typed-array@^1.1.3, is-typed-array@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" - integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" + which-typed-array "^1.1.11" is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" @@ -6504,9 +6599,9 @@ keyv@^3.0.0: json-buffer "3.0.0" keyv@^4.0.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" - integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== + version "4.5.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" + integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== dependencies: json-buffer "3.0.1" @@ -7134,6 +7229,11 @@ methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micro-ftch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" + integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== + micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -7488,7 +7588,7 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.6.0: +neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -7531,9 +7631,9 @@ node-fetch@2.6.7: whatwg-url "^5.0.0" node-fetch@^2.6.1, node-fetch@^2.6.12, node-fetch@^2.6.7: - version "2.6.12" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" - integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" @@ -8722,11 +8822,11 @@ resolve@1.17.0: path-parse "^1.0.6" resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.8.1, resolve@~1.22.1: - version "1.22.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" - integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + version "1.22.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" + integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== dependencies: - is-core-module "^2.11.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -8926,7 +9026,7 @@ semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: +semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -9172,16 +9272,16 @@ sol2uml@2.2.0: klaw "^4.0.1" sol2uml@^2.5.4: - version "2.5.6" - resolved "https://registry.yarnpkg.com/sol2uml/-/sol2uml-2.5.6.tgz#7ab18b40dc7b8c0135ae103ec519dd616b550fc2" - integrity sha512-AN0Iu6x61L36mJWlzL3jsBQQ2VzFxdYdpcACUaoO9buM+7VuQICDBel8fG26EkW87Plqui+mxrgqfpFv/Ye2vQ== + version "2.5.13" + resolved "https://registry.yarnpkg.com/sol2uml/-/sol2uml-2.5.13.tgz#095f34e7ab0e7e62e0680b7eb2dcb32bcf408bc7" + integrity sha512-ACfGQzfciKuCZw7//P2URj1bRHoX/KnJweuPKNcctzalSZGsjNdw8uRzLl1ph00F9xqu4z9wpDGWJ0GSzox2SQ== dependencies: "@aduh95/viz.js" "^3.7.0" - "@solidity-parser/parser" "^0.15.0" + "@solidity-parser/parser" "^0.16.1" axios "^1.3.4" axios-debug-log "^1.0.0" cli-color "^2.0.3" - commander "^10.0.0" + commander "^11.0.0" convert-svg-to-png "^0.6.4" debug "^4.3.4" diff-match-patch "^1.0.5" @@ -9237,9 +9337,9 @@ solhint-plugin-prettier@^0.0.5: prettier-linter-helpers "^1.0.0" solhint@^3.2.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.4.1.tgz#8ea15b21c13d1be0b53fd46d605a24d0b36a0c46" - integrity sha512-pzZn2RlZhws1XwvLPVSsxfHrwsteFf5eySOhpAytzXwKQYbTCJV6z8EevYDiSVKMpWrvbKpEtJ055CuEmzp4Xg== + version "3.6.2" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.6.2.tgz#2b2acbec8fdc37b2c68206a71ba89c7f519943fe" + integrity sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ== dependencies: "@solidity-parser/parser" "^0.16.0" ajv "^6.12.6" @@ -9254,17 +9354,19 @@ solhint@^3.2.0: js-yaml "^4.1.0" lodash "^4.17.21" pluralize "^8.0.0" - semver "^6.3.0" + semver "^7.5.2" strip-ansi "^6.0.1" table "^6.8.1" text-table "^0.2.0" optionalDependencies: prettier "^2.8.3" -solidity-ast@^0.4.15: - version "0.4.49" - resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.49.tgz#ecba89d10c0067845b7848c3a3e8cc61a4fc5b82" - integrity sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ== +solidity-ast@^0.4.26: + version "0.4.52" + resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.52.tgz#9f1a9abc7e5ba28bbf91146ecd07aec7e70f3c85" + integrity sha512-iOya9BSiB9jhM8Vf40n8lGELGzwrUc57rl5BhfNtJ5cvAaMvRcNlHeAMNvqJJyjoUnczqRbHqdivEqK89du3Cw== + dependencies: + array.prototype.findlast "^1.2.2" solidity-comments-extractor@^0.0.7: version "0.0.7" @@ -10077,6 +10179,25 @@ typechain@^5.1.2: prettier "^2.1.2" ts-essentials "^7.0.1" +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + typed-array-byte-offset@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" @@ -10170,9 +10291,9 @@ underscore@1.9.1: integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== undici@^5.14.0, undici@^5.4.0: - version "5.22.1" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.22.1.tgz#877d512effef2ac8be65e695f3586922e1a57d7b" - integrity sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw== + version "5.23.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.23.0.tgz#e7bdb0ed42cebe7b7aca87ced53e6eaafb8f8ca0" + integrity sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg== dependencies: busboy "^1.6.0" @@ -10328,9 +10449,9 @@ v8-compile-cache-lib@^3.0.1: integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + version "2.4.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" + integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== validate-npm-package-license@^3.0.1: version "3.0.4" @@ -11002,7 +11123,7 @@ web3-shh@1.7.4: web3-core-subscriptions "1.7.4" web3-net "1.7.4" -web3-utils@1.10.0, web3-utils@^1.0.0-beta.31, web3-utils@^1.3.0: +web3-utils@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.0.tgz#ca4c1b431a765c14ac7f773e92e0fd9377ccf578" integrity sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg== @@ -11042,6 +11163,20 @@ web3-utils@1.7.4: randombytes "^2.1.0" utf8 "3.0.0" +web3-utils@^1.0.0-beta.31, web3-utils@^1.3.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.10.1.tgz#97532130d85358628bc0ff14d94b7e9449786983" + integrity sha512-r6iUUw/uMnNcWXjhRv33Nyrhxq3VGOPBXeSzxhOXIci4SvC/LPTpROY0uTrMX7ztKyODYrHp8WhTkEf+ZnHssw== + dependencies: + "@ethereumjs/util" "^8.1.0" + bn.js "^5.2.1" + ethereum-bloom-filters "^1.0.6" + ethereum-cryptography "^2.1.2" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + web3@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/web3/-/web3-1.10.0.tgz#2fde0009f59aa756c93e07ea2a7f3ab971091274" @@ -11144,17 +11279,16 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== -which-typed-array@^1.1.10, which-typed-array@^1.1.2: - version "1.1.10" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.10.tgz#74baa2789991905c2076abb317103b866c64e69e" - integrity sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA== +which-typed-array@^1.1.10, which-typed-array@^1.1.11, which-typed-array@^1.1.2: + version "1.1.11" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" + integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== dependencies: available-typed-arrays "^1.0.5" call-bind "^1.0.2" for-each "^0.3.3" gopd "^1.0.1" has-tostringtag "^1.0.0" - is-typed-array "^1.1.10" which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: version "1.3.1" @@ -11183,9 +11317,9 @@ window-size@^0.2.0: integrity sha512-UD7d8HFA2+PZsbKyaOCEy8gMh1oDtHgJh1LfgjQ4zVXmYjAT/kvz3PueITKuqDiIXQe7yzpPnxX3lNc+AhQMyw== word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== wordwrap@^1.0.0: version "1.0.0" From 864fa61278e8ad76d0c1a04a32826606bd2ee5c5 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 25 Aug 2023 19:47:56 +0200 Subject: [PATCH 150/163] Update address --- scripts/goerli-deployment/createTokenBridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts index c802a6d752..f319ab96f4 100644 --- a/scripts/goerli-deployment/createTokenBridge.ts +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -14,7 +14,7 @@ export const envVars = { childChainRpc: process.env['ORBIT_RPC'] as string, } -const L1_TOKEN_BRIDGE_CREATOR = '0xce1CAd780c529e66e3aa6D952a1ED9A6447791c1' +const L1_TOKEN_BRIDGE_CREATOR = '0x8B565027E42C5115e420e2ebcF58C8881df6C098' /** * Steps: From 9d8cc955507de5624fd1df1d0dde5e4f3043a8ef Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 31 Aug 2023 10:01:37 +0200 Subject: [PATCH 151/163] Revert with custom error if deployment already exists --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 6d81b1d6f4..06114ea841 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -22,6 +22,8 @@ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; * @dev L1AtomicTokenBridgeCreator shall call `deployL2Contracts` using retryable and that will result in deployment of canonical token bridge contracts. */ contract L2AtomicTokenBridgeFactory { + error L2AtomicTokenBridgeFactory_AlreadyExists(); + function deployL2Contracts( L2RuntimeCode calldata l2Code, address l1Router, @@ -32,7 +34,13 @@ contract L2AtomicTokenBridgeFactory { address l2StandardGatewayCanonicalAddress, address rollupOwner ) external { - // create proxyAdmin which will be used for all contracts + // create proxyAdmin which will be used for all contracts. Revert if canonical deployment already exists + address proxyAdminAddress = Create2.computeAddress( + _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), keccak256(type(ProxyAdmin).creationCode), address(this) + ); + if (proxyAdminAddress.code.length > 0) { + revert L2AtomicTokenBridgeFactory_AlreadyExists(); + } address proxyAdmin = address(new ProxyAdmin{ salt: _getL2Salt(OrbitSalts.L2_PROXY_ADMIN) }()); // deploy router/gateways From e773cc25ff489ee7116e728c6907bf009157b916 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 31 Aug 2023 10:58:45 +0200 Subject: [PATCH 152/163] Extract proxy deployments to _deploySeedProxy --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 65 +++++++------------ 1 file changed, 23 insertions(+), 42 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 06114ea841..16cd8a7630 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -60,13 +60,8 @@ contract L2AtomicTokenBridgeFactory { address proxyAdmin ) internal returns (address) { // canonical L2 router with dummy logic - address canonicalRouter = address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_ROUTER) }( - address(new CanonicalAddressSeed{ salt: _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC) }()), - proxyAdmin, - bytes("") - ) - ); + address canonicalRouter = + _deploySeedProxy(proxyAdmin, _getL2Salt(OrbitSalts.L2_ROUTER), _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC)); // create L2 router logic and upgrade address routerLogic = Create2.deploy(0, _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), _creationCodeFor(runtimeCode)); @@ -85,16 +80,8 @@ contract L2AtomicTokenBridgeFactory { address proxyAdmin ) internal { // canonical L2 standard gateway with dummy logic - address canonicalStdGateway = address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY) }( - address( - new CanonicalAddressSeed{ - salt: _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC) - }() - ), - proxyAdmin, - bytes("") - ) + address canonicalStdGateway = _deploySeedProxy( + proxyAdmin, _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY), _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC) ); // create L2 standard gateway logic and upgrade @@ -125,16 +112,8 @@ contract L2AtomicTokenBridgeFactory { address proxyAdmin ) internal { // canonical L2 custom gateway with dummy logic - address canonicalCustomGateway = address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY) }( - address( - new CanonicalAddressSeed{ - salt: _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC) - }() - ), - proxyAdmin, - bytes("") - ) + address canonicalCustomGateway = _deploySeedProxy( + proxyAdmin, _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY), _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC) ); // create L2 custom gateway logic and upgrade @@ -155,13 +134,8 @@ contract L2AtomicTokenBridgeFactory { address proxyAdmin ) internal { // canonical L2 WETH with dummy logic - address canonicalL2Weth = address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH) }( - address(new CanonicalAddressSeed{ salt: _getL2Salt(OrbitSalts.L2_WETH_LOGIC) }()), - proxyAdmin, - bytes("") - ) - ); + address canonicalL2Weth = + _deploySeedProxy(proxyAdmin, _getL2Salt(OrbitSalts.L2_WETH), _getL2Salt(OrbitSalts.L2_WETH_LOGIC)); // create L2WETH logic and upgrade address l2WethLogic = @@ -169,14 +143,8 @@ contract L2AtomicTokenBridgeFactory { ProxyAdmin(proxyAdmin).upgrade(ITransparentUpgradeableProxy(canonicalL2Weth), l2WethLogic); // canonical L2 WETH gateway with dummy logic - address canonicalL2WethGateway = address( - new TransparentUpgradeableProxy{ salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY) }( - address( - new CanonicalAddressSeed{ salt: _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC) }() - ), - proxyAdmin, - bytes("") - ) + address canonicalL2WethGateway = _deploySeedProxy( + proxyAdmin, _getL2Salt(OrbitSalts.L2_WETH_GATEWAY), _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC) ); // create L2WETH gateway logic and upgrade @@ -197,6 +165,19 @@ contract L2AtomicTokenBridgeFactory { return keccak256(abi.encodePacked(prefix, msg.sender)); } + /** + * Deploys a proxy with empty logic contract in order to get deterministic address which does not depend on actual logic contract. + */ + function _deploySeedProxy(address proxyAdmin, bytes32 proxySalt, bytes32 logicSalt) internal returns (address) { + return address( + new TransparentUpgradeableProxy{ salt: proxySalt }( + address(new CanonicalAddressSeed{ salt: logicSalt}()), + proxyAdmin, + bytes("") + ) + ); + } + /** * @notice Generate a creation code that results on a contract with `code` as bytecode. * Source - https://github.com/0xsequence/sstore2/blob/master/contracts/utils/Bytecode.sol From b157eb9bb32d80d024e3f0f24d3e99a8b6bc42f5 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 31 Aug 2023 12:49:01 +0200 Subject: [PATCH 153/163] Add function descriptions --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 5 +++++ .../ethereum/L1AtomicTokenBridgeCreator.sol | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index 16cd8a7630..7bd3d7d674 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -161,6 +161,11 @@ contract L2AtomicTokenBridgeFactory { aeWETH(payable(canonicalL2Weth)).initialize("WETH", "WETH", 18, canonicalL2WethGateway, l1Weth); } + /** + * In addition to hard-coded prefix, salt for L2 contracts depends on msg.sender. Deploying L2 token bridge contracts is + * permissionless. By making msg.sender part of the salt we know exactly which set of contracts is the "canonical" one, + * deployed by L1TokenBridgeRetryableSender via retryable ticket. + */ function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { return keccak256(abi.encodePacked(prefix, msg.sender)); } diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 7e5f0ee69b..fc4bd0d3e7 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -496,10 +496,21 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return IInbox(inbox).bridge().rollup().owner(); } + /** + * We want to have exactly one set of canonical token bridge contracts for every rollup. For that + * reason we make rollup's inbox address part of the salt. It prevents deploying more than one + * token bridge. + */ function _getL1Salt(bytes32 prefix, address inbox) internal pure returns (bytes32) { return keccak256(abi.encodePacked(prefix, inbox)); } + /** + * Salt for L2 token bridge contracts depends on the caller's address. Canonical token bridge + * will be deployed by retryable ticket which is created by `retryableSender` contract. That + * means `retryableSender`'s alias will be used on L2 side to calculate the salt for deploying + * L2 contracts (_getL2Salt function in L2AtomicTokenBridgeFactory). + */ function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { return keccak256(abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(retryableSender)))); } From a93fef9c3cad5de2b56f6cbf9ea2c18f6b28e7a1 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 31 Aug 2023 13:08:33 +0200 Subject: [PATCH 154/163] Extract L2 proxy address calculation --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 107 +++++------------- 1 file changed, 28 insertions(+), 79 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index fc4bd0d3e7..83d752b6d2 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -355,98 +355,26 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function getCanonicalL2RouterAddress() public view returns (address) { - address logicSeedAddress = Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), - keccak256(type(CanonicalAddressSeed).creationCode), - canonicalL2FactoryAddress - ); - - return Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_ROUTER), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) - ) - ), - canonicalL2FactoryAddress - ); + return _getProxyAddress(_getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), _getL2Salt(OrbitSalts.L2_ROUTER)); } function getCanonicalL2StandardGatewayAddress() public view returns (address) { - address logicSeedAddress = Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), - keccak256(type(CanonicalAddressSeed).creationCode), - canonicalL2FactoryAddress - ); - - return Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) - ) - ), - canonicalL2FactoryAddress + return _getProxyAddress( + _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY) ); } function getCanonicalL2CustomGatewayAddress() public view returns (address) { - address logicSeedAddress = Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), - keccak256(type(CanonicalAddressSeed).creationCode), - canonicalL2FactoryAddress - ); - - return Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) - ) - ), - canonicalL2FactoryAddress - ); + return + _getProxyAddress(_getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY)); } function getCanonicalL2WethGatewayAddress() public view returns (address) { - address logicSeedAddress = Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), - keccak256(type(CanonicalAddressSeed).creationCode), - canonicalL2FactoryAddress - ); - - return Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_WETH_GATEWAY), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) - ) - ), - canonicalL2FactoryAddress - ); + return _getProxyAddress(_getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), _getL2Salt(OrbitSalts.L2_WETH_GATEWAY)); } function getCanonicalL2WethAddress() public view returns (address) { - address logicSeedAddress = Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_WETH_LOGIC), - keccak256(type(CanonicalAddressSeed).creationCode), - canonicalL2FactoryAddress - ); - - return Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_WETH), - keccak256( - abi.encodePacked( - type(TransparentUpgradeableProxy).creationCode, - abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) - ) - ), - canonicalL2FactoryAddress - ); + return _getProxyAddress(_getL2Salt(OrbitSalts.L2_WETH_LOGIC), _getL2Salt(OrbitSalts.L2_WETH)); } /** @@ -496,6 +424,27 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return IInbox(inbox).bridge().rollup().owner(); } + /** + * L2 contracts are deployed as proxy with dummy seed logic contracts using CREATE2. That enables + * us to upfront calculate the expected canonical addresses. + */ + function _getProxyAddress(bytes32 logicSalt, bytes32 proxySalt) internal view returns (address) { + address logicSeedAddress = Create2.computeAddress( + logicSalt, keccak256(type(CanonicalAddressSeed).creationCode), canonicalL2FactoryAddress + ); + + return Create2.computeAddress( + proxySalt, + keccak256( + abi.encodePacked( + type(TransparentUpgradeableProxy).creationCode, + abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) + ) + ), + canonicalL2FactoryAddress + ); + } + /** * We want to have exactly one set of canonical token bridge contracts for every rollup. For that * reason we make rollup's inbox address part of the salt. It prevents deploying more than one From 2ecec9a9ddf14874a39b7d827726ef32e4049251 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 1 Sep 2023 08:13:31 +0200 Subject: [PATCH 155/163] Update smart contracts and script to reflect latest rollup ownership design Rollup and rollup proxy admin are owned by L1 upgrade executor, on which the rollupOwner has EXECUTOR role. When creating token bridge for rollup, now rollupOwner has to be provided as well. L1 creator will check that rollupOwner has EXECUTOR role on the upgrade executor (which is fetched via .owner()). Aliased L1 upgrade executor and rollup owner are then made executors on L2 upgrade executor. --- .env-sample | 10 +- .../ethereum/L1AtomicTokenBridgeCreator.sol | 129 ++++++++++-------- .../ethereum/L1TokenBridgeRetryableSender.sol | 6 +- hardhat.config.ts | 2 +- scripts/atomicTokenBridgeDeployer.ts | 4 +- .../goerli-deployment/createTokenBridge.ts | 38 +++--- .../deployTokenBridgeCreator.ts | 2 +- .../deployCreatorAndCreateTokenBridge.ts | 3 +- 8 files changed, 104 insertions(+), 90 deletions(-) diff --git a/.env-sample b/.env-sample index a496dd2487..c3d66993b0 100644 --- a/.env-sample +++ b/.env-sample @@ -1,11 +1,13 @@ .env-sample + +## Rollup on top of which token bridge will be created +ROLLUP_ADDRESS="" +ROLLUP_OWNER="" +L1_TOKEN_BRIDGE_CREATOR="" + ## RPC endpoints BASECHAIN_RPC="" ORBIT_RPC="" ## Deployer key used for deploying creator and creating token bridge BASECHAIN_DEPLOYER_KEY="" - -## Optional args, used for verification script. If not provided info is read from network.json -ROLLUP_ADDRESS="" -L1_TOKEN_BRIDGE_CREATOR="" diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 77c99aea3d..e5d937b1df 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.4; import { L1TokenBridgeRetryableSender, - L1Addresses, + L1DeploymentAddresses, RetryableParams, L2TemplateAddresses, IERC20Inbox, @@ -25,7 +25,10 @@ import { ProxyAdmin } from "../arbitrum/L2AtomicTokenBridgeFactory.sol"; import {BytesLib} from "../libraries/BytesLib.sol"; -import {IUpgradeExecutor} from "@offchainlabs/upgrade-executor/src/IUpgradeExecutor.sol"; +import { + IUpgradeExecutor, + UpgradeExecutor +} from "@offchainlabs/upgrade-executor/src/UpgradeExecutor.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; import {IInbox, IBridge, IOwnable} from "@arbitrum/nitro-contracts/src/bridge/IInbox.sol"; import {AddressAliasHelper} from "../libraries/AddressAliasHelper.sol"; @@ -38,6 +41,8 @@ import { } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import {IAccessControlUpgradeable} from + "@openzeppelin/contracts-upgradeable/access/IAccessControlUpgradeable.sol"; /** * @title Layer1 token bridge creator @@ -50,6 +55,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { error L1AtomicTokenBridgeCreator_OnlyRollupOwner(); error L1AtomicTokenBridgeCreator_InvalidRouterAddr(); error L1AtomicTokenBridgeCreator_TemplatesNotSet(); + error L1AtomicTokenBridgeCreator_RollupOwnershipMisconfig(); error L1AtomicTokenBridgeCreator_ProxyAdminNotFound(); event OrbitTokenBridgeCreated( @@ -178,46 +184,55 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { * because L1 salts are already used at that point and L1 contracts are already deployed at canonical addresses * for that inbox. */ - function createTokenBridge(address inbox, uint256 maxGasForContracts, uint256 gasPriceBid) - external - payable - { + function createTokenBridge( + address inbox, + address rollupOwner, + uint256 maxGasForContracts, + uint256 gasPriceBid + ) external payable { + // templates have to be in place if (address(l1Templates.routerTemplate) == address(0)) { revert L1AtomicTokenBridgeCreator_TemplatesNotSet(); } - bool isUsingFeeToken = _getFeeToken(inbox) != address(0); - address rollupOwner = _getRollupOwner(inbox); + // Check that the rollupOwner account has EXECUTOR role + // on the upgrade executor which is the owner of the rollup + address upgradeExecutor = IInbox(inbox).bridge().rollup().owner(); + if ( + !IAccessControlUpgradeable(upgradeExecutor).hasRole( + UpgradeExecutor(upgradeExecutor).EXECUTOR_ROLE(), rollupOwner + ) + ) { + revert L1AtomicTokenBridgeCreator_RollupOwnershipMisconfig(); + } /// deploy L1 side of token bridge - ( - address router, - address standardGateway, - address customGateway, - address wethGateway, - address proxyAdmin - ) = _deployL1Contracts(inbox, rollupOwner, isUsingFeeToken); + bool isUsingFeeToken = _getFeeToken(inbox) != address(0); + L1DeploymentAddresses memory l1DeploymentAddresses = + _deployL1Contracts(inbox, rollupOwner, upgradeExecutor, isUsingFeeToken); /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls if (isUsingFeeToken) { _deployL2Factory(inbox, gasPriceBid, isUsingFeeToken); _deployL2ContractsUsingFeeToken( - L1Addresses(router, standardGateway, customGateway, address(0), address(0)), + l1DeploymentAddresses, inbox, maxGasForContracts, gasPriceBid, - proxyAdmin + rollupOwner, + upgradeExecutor ); } else { uint256 valueSpentForFactory = _deployL2Factory(inbox, gasPriceBid, isUsingFeeToken); uint256 fundsRemaining = msg.value - valueSpentForFactory; _deployL2ContractsUsingEth( - L1Addresses(router, standardGateway, customGateway, wethGateway, l1Weth), + l1DeploymentAddresses, inbox, maxGasForContracts, gasPriceBid, fundsRemaining, - proxyAdmin + rollupOwner, + upgradeExecutor ); } } @@ -227,7 +242,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { * @dev Non-canonical router can be unregistered by re-setting it to address(0) - it makes canonical router the valid one. */ function setNonCanonicalRouter(address inbox, address nonCanonicalRouter) external { - if (msg.sender != _getRollupOwner(inbox)) { + if (msg.sender != IInbox(inbox).bridge().rollup().owner()) { revert L1AtomicTokenBridgeCreator_OnlyRollupOwner(); } if (nonCanonicalRouter == getCanonicalL1RouterAddress(inbox)) { @@ -248,28 +263,23 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return getCanonicalL1RouterAddress(inbox); } - function _deployL1Contracts(address inbox, address rollupOwner, bool isUsingFeeToken) - internal - returns ( - address router, - address standardGateway, - address customGateway, - address wethGateway, - address proxyAdmin - ) - { + function _deployL1Contracts( + address inbox, + address rollupOwner, + address upgradeExecutor, + bool isUsingFeeToken + ) internal returns (L1DeploymentAddresses memory l1Addresses) { // get existing proxy admin and upgrade executor - proxyAdmin = IInbox_ProxyAdmin(inbox).getProxyAdmin(); + address proxyAdmin = IInbox_ProxyAdmin(inbox).getProxyAdmin(); if (proxyAdmin == address(0)) { revert L1AtomicTokenBridgeCreator_ProxyAdminNotFound(); } - address upgradeExecutor = ProxyAdmin(proxyAdmin).owner(); // deploy router address routerTemplate = isUsingFeeToken ? address(l1Templates.feeTokenBasedRouterTemplate) : address(l1Templates.routerTemplate); - router = address( + l1Addresses.router = address( new TransparentUpgradeableProxy{ salt: _getL1Salt(OrbitSalts.L1_ROUTER, inbox) }( routerTemplate, proxyAdmin, @@ -278,15 +288,20 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); // deploy and init gateways - standardGateway = _deployL1StandardGateway(proxyAdmin, router, inbox, isUsingFeeToken); - customGateway = - _deployL1CustomGateway(proxyAdmin, router, inbox, upgradeExecutor, isUsingFeeToken); - wethGateway = isUsingFeeToken ? address(0) : _deployL1WethGateway(proxyAdmin, router, inbox); + l1Addresses.standardGateway = + _deployL1StandardGateway(proxyAdmin, l1Addresses.router, inbox, isUsingFeeToken); + l1Addresses.customGateway = _deployL1CustomGateway( + proxyAdmin, l1Addresses.router, inbox, upgradeExecutor, isUsingFeeToken + ); + l1Addresses.wethGateway = isUsingFeeToken + ? address(0) + : _deployL1WethGateway(proxyAdmin, l1Addresses.router, inbox); + l1Addresses.weth = isUsingFeeToken ? address(0) : l1Weth; // init router - L1GatewayRouter(router).initialize( + L1GatewayRouter(l1Addresses.router).initialize( upgradeExecutor, - address(standardGateway), + l1Addresses.standardGateway, address(0), getCanonicalL2RouterAddress(), inbox @@ -296,10 +311,10 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { emit OrbitTokenBridgeCreated( inbox, rollupOwner, - router, - standardGateway, - customGateway, - wethGateway, + l1Addresses.router, + l1Addresses.standardGateway, + l1Addresses.customGateway, + l1Addresses.wethGateway, proxyAdmin, upgradeExecutor ); @@ -338,7 +353,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address proxyAdmin, address router, address inbox, - address owner, + address upgradeExecutor, bool isUsingFeeToken ) internal returns (address) { address template = isUsingFeeToken @@ -353,7 +368,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ) ); - customGateway.initialize(getCanonicalL2CustomGatewayAddress(), router, inbox, owner); + customGateway.initialize( + getCanonicalL2CustomGatewayAddress(), router, inbox, upgradeExecutor + ); return address(customGateway); } @@ -424,15 +441,14 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } function _deployL2ContractsUsingEth( - L1Addresses memory l1Addresses, + L1DeploymentAddresses memory l1Addresses, address inbox, uint256 maxGas, uint256 gasPriceBid, uint256 availableFunds, - address proxyAdmin + address rollupOwner, + address upgradeExecutor ) internal { - address upgradeExecutor = ProxyAdmin(proxyAdmin).owner(); - retryableSender.sendRetryableUsingEth{value: availableFunds}( RetryableParams( inbox, canonicalL2FactoryAddress, msg.sender, msg.sender, maxGas, gasPriceBid @@ -448,21 +464,20 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ), l1Addresses, getCanonicalL2StandardGatewayAddress(), - _getRollupOwner(inbox), + rollupOwner, msg.sender, AddressAliasHelper.applyL1ToL2Alias(upgradeExecutor) ); } function _deployL2ContractsUsingFeeToken( - L1Addresses memory l1Addresses, + L1DeploymentAddresses memory l1Addresses, address inbox, uint256 maxGas, uint256 gasPriceBid, - address proxyAdmin + address rollupOwner, + address upgradeExecutor ) internal { - address upgradeExecutor = ProxyAdmin(proxyAdmin).owner(); - // transfer fee tokens to inbox to pay for 2nd retryable address feeToken = _getFeeToken(inbox); uint256 fee = maxGas * gasPriceBid; @@ -483,7 +498,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ), l1Addresses, getCanonicalL2StandardGatewayAddress(), - _getRollupOwner(inbox), + rollupOwner, AddressAliasHelper.applyL1ToL2Alias(upgradeExecutor) ); } @@ -604,10 +619,6 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { return abi.encodePacked(hex"63", uint32(code.length), hex"80600E6000396000F3", code); } - function _getRollupOwner(address inbox) internal view returns (address) { - return IInbox(inbox).bridge().rollup().owner(); - } - /** * L2 contracts are deployed as proxy with dummy seed logic contracts using CREATE2. That enables * us to upfront calculate the expected canonical addresses. diff --git a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol index 1a16f24af0..bde3de250b 100644 --- a/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol +++ b/contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol @@ -41,7 +41,7 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { function sendRetryableUsingEth( RetryableParams calldata retryableParams, L2TemplateAddresses calldata l2, - L1Addresses calldata l1, + L1DeploymentAddresses calldata l1, address l2StandardGatewayAddress, address rollupOwner, address deployer, @@ -90,7 +90,7 @@ contract L1TokenBridgeRetryableSender is Initializable, OwnableUpgradeable { function sendRetryableUsingFeeToken( RetryableParams calldata retryableParams, L2TemplateAddresses calldata l2, - L1Addresses calldata l1, + L1DeploymentAddresses calldata l1, address l2StandardGatewayAddress, address rollupOwner, address aliasedL1UpgradeExecutor @@ -188,7 +188,7 @@ struct L2TemplateAddresses { /** * L1 side of token bridge addresses */ -struct L1Addresses { +struct L1DeploymentAddresses { address router; address standardGateway; address customGateway; diff --git a/hardhat.config.ts b/hardhat.config.ts index e641a55748..b718396056 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -36,7 +36,7 @@ const config = { }, }, { - version: '0.8.17', + version: '0.8.16', settings: { optimizer: { enabled: true, diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index cbd3feee25..d1b2753970 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -53,7 +53,8 @@ export const createTokenBridge = async ( l1Signer: Signer, l2Provider: ethers.providers.Provider, l1TokenBridgeCreator: L1AtomicTokenBridgeCreator, - rollupAddress: string + rollupAddress: string, + rollupOwnerAddress: string ) => { const gasPrice = await l2Provider.getGasPrice() @@ -125,6 +126,7 @@ export const createTokenBridge = async ( const receipt = await ( await l1TokenBridgeCreator.createTokenBridge( inbox, + rollupOwnerAddress, maxGasForContracts, gasPrice, { value: retryableFee } diff --git a/scripts/goerli-deployment/createTokenBridge.ts b/scripts/goerli-deployment/createTokenBridge.ts index f319ab96f4..b2a6039300 100644 --- a/scripts/goerli-deployment/createTokenBridge.ts +++ b/scripts/goerli-deployment/createTokenBridge.ts @@ -5,17 +5,19 @@ import { createTokenBridge, getSigner } from '../atomicTokenBridgeDeployer' import dotenv from 'dotenv' import { L1AtomicTokenBridgeCreator__factory } from '../../build/types' import * as fs from 'fs' +import { env } from 'process' dotenv.config() export const envVars = { + rollupAddress: process.env['ROLLUP_ADDRESS'] as string, + rollupOwner: process.env['ROLLUP_OWNER'] as string, + l1TokenBridgeCreator: process.env['L1_TOKEN_BRIDGE_CREATOR'] as string, baseChainRpc: process.env['BASECHAIN_RPC'] as string, baseChainDeployerKey: process.env['BASECHAIN_DEPLOYER_KEY'] as string, childChainRpc: process.env['ORBIT_RPC'] as string, } -const L1_TOKEN_BRIDGE_CREATOR = '0x8B565027E42C5115e420e2ebcF58C8881df6C098' - /** * Steps: * - read network info from local container and register networks @@ -29,7 +31,13 @@ const L1_TOKEN_BRIDGE_CREATOR = '0x8B565027E42C5115e420e2ebcF58C8881df6C098' * @param l2Url * @returns */ -export const createTokenBridgeOnGoerli = async (rollupAddress: string) => { +export const createTokenBridgeOnGoerli = async () => { + if (envVars.rollupAddress == undefined) + throw new Error('Missing ROLLUP_ADDRESS in env vars') + if (envVars.rollupOwner == undefined) + throw new Error('Missing ROLLUP_OWNER in env vars') + if (envVars.l1TokenBridgeCreator == undefined) + throw new Error('Missing L1_TOKEN_BRIDGE_CREATOR in env vars') if (envVars.baseChainRpc == undefined) throw new Error('Missing BASECHAIN_RPC in env vars') if (envVars.baseChainDeployerKey == undefined) @@ -37,6 +45,8 @@ export const createTokenBridgeOnGoerli = async (rollupAddress: string) => { if (envVars.childChainRpc == undefined) throw new Error('Missing ORBIT_RPC in env vars') + console.log('Creating token bridge for rollup', envVars.rollupAddress) + const l1Provider = new JsonRpcProvider(envVars.baseChainRpc) const l1Deployer = getSigner(l1Provider, envVars.baseChainDeployerKey) const l2Provider = new JsonRpcProvider(envVars.childChainRpc) @@ -44,11 +54,11 @@ export const createTokenBridgeOnGoerli = async (rollupAddress: string) => { const { l1Network, l2Network: corel2Network } = await registerGoerliNetworks( l1Provider, l2Provider, - rollupAddress + envVars.rollupAddress ) const l1TokenBridgeCreator = L1AtomicTokenBridgeCreator__factory.connect( - L1_TOKEN_BRIDGE_CREATOR, + envVars.l1TokenBridgeCreator, l1Deployer ) @@ -57,7 +67,8 @@ export const createTokenBridgeOnGoerli = async (rollupAddress: string) => { l1Deployer, l2Provider, l1TokenBridgeCreator, - rollupAddress + envVars.rollupAddress, + envVars.rollupOwner ) const l2Network = { @@ -159,20 +170,7 @@ const registerGoerliNetworks = async ( } async function main() { - const args = process.argv.slice(2) - if (args.length != 1) { - console.log( - "Please provide exactly 1 argument - rollup address.\nIe. `yarn run create:goerli:token-bridge -- '0xDAB64b6E86035Aa9EB697341B663fb4B46930E60'`" - ) - return - } - - const rollupAddress = args[0] - console.log('Creating token bridge for rollup', rollupAddress) - - const { l1Network, l2Network } = await createTokenBridgeOnGoerli( - rollupAddress - ) + const { l1Network, l2Network } = await createTokenBridgeOnGoerli() const NETWORK_FILE = 'network.json' fs.writeFileSync( NETWORK_FILE, diff --git a/scripts/goerli-deployment/deployTokenBridgeCreator.ts b/scripts/goerli-deployment/deployTokenBridgeCreator.ts index 5390628f1f..e28493dcb4 100644 --- a/scripts/goerli-deployment/deployTokenBridgeCreator.ts +++ b/scripts/goerli-deployment/deployTokenBridgeCreator.ts @@ -127,7 +127,7 @@ const registerGoerliNetworks = async ( async function main() { // this is just random Orbit rollup that will be used to estimate gas needed to deploy L2 token bridge factory via retryable - const rollupAddress = '0x3c8045E038d9Ce79D2D05cB75B223dbDDF97403B' + const rollupAddress = '0xe16E44efb06F33ed700618A738E24FeFd7801A84' const l1TokenBridgeCreator = await deployTokenBridgeCreator(rollupAddress) console.log('L1TokenBridgeCreator:', l1TokenBridgeCreator.address) } diff --git a/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts b/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts index 41af973f43..2dbac143c5 100644 --- a/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts +++ b/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts @@ -86,7 +86,8 @@ export const setupTokenBridgeInLocalEnv = async () => { l1Deployer, l2Deployer.provider!, l1TokenBridgeCreator, - coreL2Network.ethBridge.rollup + coreL2Network.ethBridge.rollup, + l1Deployer.address ) const l2Network: L2Network = { From 8aca11999392954eeb1874944edbe33f842d998e Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 7 Sep 2023 09:35:28 +0200 Subject: [PATCH 156/163] Add docs for computeAddress function --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index 83d752b6d2..c4dcd97fd9 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -379,6 +379,15 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { /** * @notice Compute address of contract deployed using CREATE opcode + * @dev The contract address is derived by RLP encoding the deployer's address and the nonce using the Keccak-256 hashing algorithm. + * More formally: keccak256(rlp.encode([origin, nonce])[12:] + * + * First part of the function implementation does RLP encoding of [origin, nonce]. + * - nonce's prefix is encoded depending on its size -> 0x80 + lenInBytes(nonce) + * - origin is 20 bytes long so its encoded prefix is 0x80 + 0x14 = 0x94 + * - prefix of the whole list is 0xc0 + lenInBytes(RLP(list)) + * After we have RLP encoding in place last step is to hash it, take last 20 bytes and cast is to an address. + * * @return computed address */ function _computeAddress(address origin, uint256 nonce) internal pure returns (address) { @@ -425,8 +434,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } /** - * L2 contracts are deployed as proxy with dummy seed logic contracts using CREATE2. That enables - * us to upfront calculate the expected canonical addresses. + * @notice L2 contracts are deployed as proxy with dummy seed logic contracts using CREATE2. That enables + * us to upfront calculate the expected canonical addresses. */ function _getProxyAddress(bytes32 logicSalt, bytes32 proxySalt) internal view returns (address) { address logicSeedAddress = Create2.computeAddress( @@ -446,19 +455,19 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } /** - * We want to have exactly one set of canonical token bridge contracts for every rollup. For that - * reason we make rollup's inbox address part of the salt. It prevents deploying more than one - * token bridge. + * @notice We want to have exactly one set of canonical token bridge contracts for every rollup. For that + * reason we make rollup's inbox address part of the salt. It prevents deploying more than one + * token bridge. */ function _getL1Salt(bytes32 prefix, address inbox) internal pure returns (bytes32) { return keccak256(abi.encodePacked(prefix, inbox)); } /** - * Salt for L2 token bridge contracts depends on the caller's address. Canonical token bridge - * will be deployed by retryable ticket which is created by `retryableSender` contract. That - * means `retryableSender`'s alias will be used on L2 side to calculate the salt for deploying - * L2 contracts (_getL2Salt function in L2AtomicTokenBridgeFactory). + * @notice Salt for L2 token bridge contracts depends on the caller's address. Canonical token bridge + * will be deployed by retryable ticket which is created by `retryableSender` contract. That + * means `retryableSender`'s alias will be used on L2 side to calculate the salt for deploying + * L2 contracts (_getL2Salt function in L2AtomicTokenBridgeFactory). */ function _getL2Salt(bytes32 prefix) internal view returns (bytes32) { return keccak256(abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(retryableSender)))); From 1f2121f47622ed7099ff66f9e9dd23433f36d456 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 7 Sep 2023 09:35:28 +0200 Subject: [PATCH 157/163] Add docs for computeAddress function --- .../ethereum/L1AtomicTokenBridgeCreator.sol | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index e5d937b1df..ece5a63de4 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -578,6 +578,15 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { /** * @notice Compute address of contract deployed using CREATE opcode + * @dev The contract address is derived by RLP encoding the deployer's address and the nonce using the Keccak-256 hashing algorithm. + * More formally: keccak256(rlp.encode([origin, nonce])[12:] + * + * First part of the function implementation does RLP encoding of [origin, nonce]. + * - nonce's prefix is encoded depending on its size -> 0x80 + lenInBytes(nonce) + * - origin is 20 bytes long so its encoded prefix is 0x80 + 0x14 = 0x94 + * - prefix of the whole list is 0xc0 + lenInBytes(RLP(list)) + * After we have RLP encoding in place last step is to hash it, take last 20 bytes and cast is to an address. + * * @return computed address */ function _computeAddress(address origin, uint256 nonce) internal pure returns (address) { @@ -620,8 +629,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } /** - * L2 contracts are deployed as proxy with dummy seed logic contracts using CREATE2. That enables - * us to upfront calculate the expected canonical addresses. + * @notice L2 contracts are deployed as proxy with dummy seed logic contracts using CREATE2. That enables + * us to upfront calculate the expected canonical addresses. */ function _getProxyAddress(bytes32 logicSalt, bytes32 proxySalt) internal @@ -645,19 +654,19 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } /** - * We want to have exactly one set of canonical token bridge contracts for every rollup. For that - * reason we make rollup's inbox address part of the salt. It prevents deploying more than one - * token bridge. + * @notice We want to have exactly one set of canonical token bridge contracts for every rollup. For that + * reason we make rollup's inbox address part of the salt. It prevents deploying more than one + * token bridge. */ function _getL1Salt(bytes memory prefix, address inbox) internal pure returns (bytes32) { return keccak256(abi.encodePacked(prefix, inbox)); } /** - * Salt for L2 token bridge contracts depends on the caller's address. Canonical token bridge - * will be deployed by retryable ticket which is created by `retryableSender` contract. That - * means `retryableSender`'s alias will be used on L2 side to calculate the salt for deploying - * L2 contracts (_getL2Salt function in L2AtomicTokenBridgeFactory). + * @notice Salt for L2 token bridge contracts depends on the caller's address. Canonical token bridge + * will be deployed by retryable ticket which is created by `retryableSender` contract. That + * means `retryableSender`'s alias will be used on L2 side to calculate the salt for deploying + * L2 contracts (_getL2Salt function in L2AtomicTokenBridgeFactory). */ function _getL2Salt(bytes memory prefix) internal view returns (bytes32) { return keccak256( From 6cb20600a3f964aa517ea024fc22346e3a0dd16d Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 7 Sep 2023 10:30:25 +0200 Subject: [PATCH 158/163] Verify retyrable sender was not frontrun --- .env-sample | 4 ++-- scripts/atomicTokenBridgeDeployer.ts | 2 +- .../deployTokenBridgeCreator.ts | 13 ++++++------- .../deployCreatorAndCreateTokenBridge.ts | 17 ++++++++++------- test-e2e/tokenBridgeDeploymentTest.ts | 17 +++++++++++++++-- 5 files changed, 34 insertions(+), 19 deletions(-) diff --git a/.env-sample b/.env-sample index c3d66993b0..0fd2718b05 100644 --- a/.env-sample +++ b/.env-sample @@ -1,9 +1,9 @@ -.env-sample - ## Rollup on top of which token bridge will be created ROLLUP_ADDRESS="" ROLLUP_OWNER="" L1_TOKEN_BRIDGE_CREATOR="" +# needed for verification +L1_RETRYABLE_SENDER="" ## RPC endpoints BASECHAIN_RPC="" diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index d1b2753970..acf7cdfbc8 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -386,7 +386,7 @@ export const deployL1TokenBridgeCreator = async ( ) ).wait() - return l1TokenBridgeCreator + return { l1TokenBridgeCreator, retryableSender } } export const getEstimateForDeployingFactory = async ( diff --git a/scripts/goerli-deployment/deployTokenBridgeCreator.ts b/scripts/goerli-deployment/deployTokenBridgeCreator.ts index e28493dcb4..eb6c1f9b01 100644 --- a/scripts/goerli-deployment/deployTokenBridgeCreator.ts +++ b/scripts/goerli-deployment/deployTokenBridgeCreator.ts @@ -45,13 +45,10 @@ export const deployTokenBridgeCreator = async (rollupAddress: string) => { await registerGoerliNetworks(l1Provider, l2Provider, rollupAddress) // deploy L1 creator and set templates - const l1TokenBridgeCreator = await deployL1TokenBridgeCreator( - l1Deployer, - l2Provider, - ARB_GOERLI_WETH - ) + const { l1TokenBridgeCreator, retryableSender } = + await deployL1TokenBridgeCreator(l1Deployer, l2Provider, ARB_GOERLI_WETH) - return l1TokenBridgeCreator + return { l1TokenBridgeCreator, retryableSender } } const registerGoerliNetworks = async ( @@ -128,8 +125,10 @@ const registerGoerliNetworks = async ( async function main() { // this is just random Orbit rollup that will be used to estimate gas needed to deploy L2 token bridge factory via retryable const rollupAddress = '0xe16E44efb06F33ed700618A738E24FeFd7801A84' - const l1TokenBridgeCreator = await deployTokenBridgeCreator(rollupAddress) + const { l1TokenBridgeCreator, retryableSender } = + await deployTokenBridgeCreator(rollupAddress) console.log('L1TokenBridgeCreator:', l1TokenBridgeCreator.address) + console.log('L1TokenBridgeRetryableSender:', retryableSender.address) } main().then(() => console.log('Done.')) diff --git a/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts b/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts index 2dbac143c5..543ebf6896 100644 --- a/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts +++ b/scripts/local-deployment/deployCreatorAndCreateTokenBridge.ts @@ -74,12 +74,10 @@ export const setupTokenBridgeInLocalEnv = async () => { // prerequisite - deploy L1 creator and set templates const l1Weth = ethers.Wallet.createRandom().address - const l1TokenBridgeCreator = await deployL1TokenBridgeCreator( - l1Deployer, - l2Deployer.provider!, - l1Weth - ) + const { l1TokenBridgeCreator, retryableSender } = + await deployL1TokenBridgeCreator(l1Deployer, l2Deployer.provider!, l1Weth) console.log('L1TokenBridgeCreator', l1TokenBridgeCreator.address) + console.log('L1TokenBridgeRetryableSender', retryableSender.address) // create token bridge const deployedContracts = await createTokenBridge( @@ -115,6 +113,7 @@ export const setupTokenBridgeInLocalEnv = async () => { l1Network, l2Network, l1TokenBridgeCreator, + retryableSender, } } @@ -198,13 +197,17 @@ export const getLocalNetworks = async ( } async function main() { - const { l1Network, l2Network, l1TokenBridgeCreator } = + const { l1Network, l2Network, l1TokenBridgeCreator, retryableSender } = await setupTokenBridgeInLocalEnv() const NETWORK_FILE = 'network.json' fs.writeFileSync( NETWORK_FILE, - JSON.stringify({ l1Network, l2Network, l1TokenBridgeCreator }, null, 2) + JSON.stringify( + { l1Network, l2Network, l1TokenBridgeCreator, retryableSender }, + null, + 2 + ) ) console.log(NETWORK_FILE + ' updated') } diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index 972cc3ced2..c93531b1f1 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -44,21 +44,24 @@ describe('tokenBridge', () => { l1Provider = new JsonRpcProvider(config.l1Url) l2Provider = new JsonRpcProvider(config.l2Url) - /// get rollup and L1 creator addresses as entrypoint, either from env vars or from network.json + /// get rollup, L1 creator and retryable sender as entrypoint, either from env vars or from network.json let rollupAddress: string let l1TokenBridgeCreator: string + let l1RetryableSender: string if (process.env.ROLLUP_ADDRESS && process.env.L1_TOKEN_BRIDGE_CREATOR) { rollupAddress = process.env.ROLLUP_ADDRESS as string l1TokenBridgeCreator = process.env.L1_TOKEN_BRIDGE_CREATOR as string + l1RetryableSender = process.env.L1_RETRYABLE_SENDER as string } else { const localNetworkFile = path.join(__dirname, '..', 'network.json') if (fs.existsSync(localNetworkFile)) { const data = JSON.parse(fs.readFileSync(localNetworkFile).toString()) rollupAddress = data['l2Network']['ethBridge']['rollup'] l1TokenBridgeCreator = data['l1TokenBridgeCreator'] + l1RetryableSender = data['retryableSender'] } else { throw new Error( - "Can't find rollup address info. Either set ROLLUP_ADDRESS env var or provide network.json file" + "Can't find rollup address info. Either set ROLLUP_ADDRESS, L1_TOKEN_BRIDGE_CREATOR AND L1_RETRYABLE_SENDER env varS or provide network.json file" ) } } @@ -71,6 +74,16 @@ describe('tokenBridge', () => { //// L1 checks + // check that setting of retryable sender was not frontrun + const actualRetryableSender = + await L1AtomicTokenBridgeCreator__factory.connect( + l1TokenBridgeCreator, + l1Provider + ).retryableSender() + expect(actualRetryableSender.toLowerCase()).to.be.eq( + l1RetryableSender.toLowerCase() + ) + await checkL1RouterInitialization( L1GatewayRouter__factory.connect(l1.router, l1Provider), l1, From 7606ab6fcf8bb3479b73c5ad7bcb0db8da484ae6 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Fri, 8 Sep 2023 15:54:14 +0200 Subject: [PATCH 159/163] Use chainId in salt for L2 contracts. --- .../arbitrum/L2AtomicTokenBridgeFactory.sol | 6 +- .../ethereum/L1AtomicTokenBridgeCreator.sol | 156 +++++++++++------- scripts/atomicTokenBridgeDeployer.ts | 23 ++- .../deployTokenBridgeCreator.ts | 2 +- test-e2e/tokenBridgeDeploymentTest.ts | 19 ++- test-foundry/util/TestUtil.sol | 2 +- 6 files changed, 135 insertions(+), 73 deletions(-) diff --git a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol index f0e9555167..4859535812 100644 --- a/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol +++ b/contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol @@ -241,12 +241,12 @@ contract L2AtomicTokenBridgeFactory { } /** - * In addition to hard-coded prefix, salt for L2 contracts depends on msg.sender. Deploying L2 token bridge contracts is - * permissionless. By making msg.sender part of the salt we know exactly which set of contracts is the "canonical" one, + * In addition to hard-coded prefix, salt for L2 contracts depends on msg.sender and the chainId. Deploying L2 token bridge contracts is + * permissionless. By making msg.sender part of the salt we know exactly which set of contracts is the "canonical" one for given chain, * deployed by L1TokenBridgeRetryableSender via retryable ticket. */ function _getL2Salt(bytes memory prefix) internal view returns (bytes32) { - return keccak256(abi.encodePacked(prefix, msg.sender)); + return keccak256(abi.encodePacked(prefix, block.chainid, msg.sender)); } /** diff --git a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol index ece5a63de4..18688745be 100644 --- a/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol +++ b/contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol @@ -108,11 +108,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { // WETH address on L1 address public l1Weth; - // immutable canonical addresses for L2 contracts + // immutable canonical address for L2 factory // other canonical addresses (dependent on L2 template implementations) can be fetched through `getCanonicalL2***Address` functions address public canonicalL2FactoryAddress; - address public canonicalL2ProxyAdminAddress; - address public canonicalL2BeaconProxyFactoryAddress; constructor() { _disableInitializers(); @@ -127,16 +125,6 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { canonicalL2FactoryAddress = _computeAddress(AddressAliasHelper.applyL1ToL2Alias(address(this)), 0); - canonicalL2ProxyAdminAddress = Create2.computeAddress( - _getL2Salt(OrbitSalts.L2_PROXY_ADMIN), - keccak256(type(ProxyAdmin).creationCode), - canonicalL2FactoryAddress - ); - canonicalL2BeaconProxyFactoryAddress = Create2.computeAddress( - _getL2Salt(OrbitSalts.BEACON_PROXY_FACTORY), - keccak256(type(BeaconProxyFactory).creationCode), - canonicalL2FactoryAddress - ); } /** @@ -206,10 +194,12 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { revert L1AtomicTokenBridgeCreator_RollupOwnershipMisconfig(); } + uint256 rollupChainId = IRollupCore(address(IInbox(inbox).bridge().rollup())).chainId(); + /// deploy L1 side of token bridge bool isUsingFeeToken = _getFeeToken(inbox) != address(0); L1DeploymentAddresses memory l1DeploymentAddresses = - _deployL1Contracts(inbox, rollupOwner, upgradeExecutor, isUsingFeeToken); + _deployL1Contracts(inbox, rollupOwner, upgradeExecutor, isUsingFeeToken, rollupChainId); /// deploy factory and then L2 contracts through L2 factory, using 2 retryables calls if (isUsingFeeToken) { @@ -220,7 +210,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { maxGasForContracts, gasPriceBid, rollupOwner, - upgradeExecutor + upgradeExecutor, + rollupChainId ); } else { uint256 valueSpentForFactory = _deployL2Factory(inbox, gasPriceBid, isUsingFeeToken); @@ -232,7 +223,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { gasPriceBid, fundsRemaining, rollupOwner, - upgradeExecutor + upgradeExecutor, + rollupChainId ); } } @@ -267,7 +259,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address inbox, address rollupOwner, address upgradeExecutor, - bool isUsingFeeToken + bool isUsingFeeToken, + uint256 chainId ) internal returns (L1DeploymentAddresses memory l1Addresses) { // get existing proxy admin and upgrade executor address proxyAdmin = IInbox_ProxyAdmin(inbox).getProxyAdmin(); @@ -288,14 +281,15 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); // deploy and init gateways - l1Addresses.standardGateway = - _deployL1StandardGateway(proxyAdmin, l1Addresses.router, inbox, isUsingFeeToken); + l1Addresses.standardGateway = _deployL1StandardGateway( + proxyAdmin, l1Addresses.router, inbox, isUsingFeeToken, chainId + ); l1Addresses.customGateway = _deployL1CustomGateway( - proxyAdmin, l1Addresses.router, inbox, upgradeExecutor, isUsingFeeToken + proxyAdmin, l1Addresses.router, inbox, upgradeExecutor, isUsingFeeToken, chainId ); l1Addresses.wethGateway = isUsingFeeToken ? address(0) - : _deployL1WethGateway(proxyAdmin, l1Addresses.router, inbox); + : _deployL1WethGateway(proxyAdmin, l1Addresses.router, inbox, chainId); l1Addresses.weth = isUsingFeeToken ? address(0) : l1Weth; // init router @@ -303,7 +297,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { upgradeExecutor, l1Addresses.standardGateway, address(0), - getCanonicalL2RouterAddress(), + getCanonicalL2RouterAddress(chainId), inbox ); @@ -324,7 +318,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address proxyAdmin, address router, address inbox, - bool isUsingFeeToken + bool isUsingFeeToken, + uint256 chainId ) internal returns (address) { address template = isUsingFeeToken ? address(l1Templates.feeTokenBasedStandardGatewayTemplate) @@ -339,11 +334,11 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); standardGateway.initialize( - getCanonicalL2StandardGatewayAddress(), + getCanonicalL2StandardGatewayAddress(chainId), router, inbox, keccak256(type(ClonableBeaconProxy).creationCode), - canonicalL2BeaconProxyFactoryAddress + getCanonicalL2BeaconProxyFactoryAddress(chainId) ); return address(standardGateway); @@ -354,7 +349,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { address router, address inbox, address upgradeExecutor, - bool isUsingFeeToken + bool isUsingFeeToken, + uint256 chainId ) internal returns (address) { address template = isUsingFeeToken ? address(l1Templates.feeTokenBasedCustomGatewayTemplate) @@ -369,16 +365,18 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); customGateway.initialize( - getCanonicalL2CustomGatewayAddress(), router, inbox, upgradeExecutor + getCanonicalL2CustomGatewayAddress(chainId), router, inbox, upgradeExecutor ); return address(customGateway); } - function _deployL1WethGateway(address proxyAdmin, address router, address inbox) - internal - returns (address) - { + function _deployL1WethGateway( + address proxyAdmin, + address router, + address inbox, + uint256 chainId + ) internal returns (address) { L1WethGateway wethGateway = L1WethGateway( payable( address( @@ -390,7 +388,11 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); wethGateway.initialize( - getCanonicalL2WethGatewayAddress(), router, inbox, l1Weth, getCanonicalL2WethAddress() + getCanonicalL2WethGatewayAddress(chainId), + router, + inbox, + l1Weth, + getCanonicalL2WethAddress(chainId) ); return address(wethGateway); @@ -447,7 +449,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { uint256 gasPriceBid, uint256 availableFunds, address rollupOwner, - address upgradeExecutor + address upgradeExecutor, + uint256 chainId ) internal { retryableSender.sendRetryableUsingEth{value: availableFunds}( RetryableParams( @@ -463,7 +466,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { l2MulticallTemplate ), l1Addresses, - getCanonicalL2StandardGatewayAddress(), + getCanonicalL2StandardGatewayAddress(chainId), rollupOwner, msg.sender, AddressAliasHelper.applyL1ToL2Alias(upgradeExecutor) @@ -476,7 +479,8 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { uint256 maxGas, uint256 gasPriceBid, address rollupOwner, - address upgradeExecutor + address upgradeExecutor, + uint256 chainId ) internal { // transfer fee tokens to inbox to pay for 2nd retryable address feeToken = _getFeeToken(inbox); @@ -497,7 +501,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { l2MulticallTemplate ), l1Addresses, - getCanonicalL2StandardGatewayAddress(), + getCanonicalL2StandardGatewayAddress(chainId), rollupOwner, AddressAliasHelper.applyL1ToL2Alias(upgradeExecutor) ); @@ -527,39 +531,71 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { ); } - function getCanonicalL2RouterAddress() public view returns (address) { + function getCanonicalL2RouterAddress(uint256 chainId) public view returns (address) { return _getProxyAddress( - _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC), _getL2Salt(OrbitSalts.L2_ROUTER) + _getL2Salt(OrbitSalts.L2_ROUTER_LOGIC, chainId), + _getL2Salt(OrbitSalts.L2_ROUTER, chainId), + chainId ); } - function getCanonicalL2StandardGatewayAddress() public view returns (address) { + function getCanonicalL2StandardGatewayAddress(uint256 chainId) public view returns (address) { return _getProxyAddress( - _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC), - _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY) + _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY_LOGIC, chainId), + _getL2Salt(OrbitSalts.L2_STANDARD_GATEWAY, chainId), + chainId ); } - function getCanonicalL2CustomGatewayAddress() public view returns (address) { + function getCanonicalL2CustomGatewayAddress(uint256 chainId) public view returns (address) { return _getProxyAddress( - _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC), _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY) + _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY_LOGIC, chainId), + _getL2Salt(OrbitSalts.L2_CUSTOM_GATEWAY, chainId), + chainId ); } - function getCanonicalL2WethGatewayAddress() public view returns (address) { + function getCanonicalL2WethGatewayAddress(uint256 chainId) public view returns (address) { return _getProxyAddress( - _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC), _getL2Salt(OrbitSalts.L2_WETH_GATEWAY) + _getL2Salt(OrbitSalts.L2_WETH_GATEWAY_LOGIC, chainId), + _getL2Salt(OrbitSalts.L2_WETH_GATEWAY, chainId), + chainId ); } - function getCanonicalL2WethAddress() public view returns (address) { - return - _getProxyAddress(_getL2Salt(OrbitSalts.L2_WETH_LOGIC), _getL2Salt(OrbitSalts.L2_WETH)); + function getCanonicalL2WethAddress(uint256 chainId) public view returns (address) { + return _getProxyAddress( + _getL2Salt(OrbitSalts.L2_WETH_LOGIC, chainId), + _getL2Salt(OrbitSalts.L2_WETH, chainId), + chainId + ); + } + + function getCanonicalL2ProxyAdminAddress(uint256 chainId) public view returns (address) { + return Create2.computeAddress( + _getL2Salt(OrbitSalts.L2_PROXY_ADMIN, chainId), + keccak256(type(ProxyAdmin).creationCode), + canonicalL2FactoryAddress + ); + } + + function getCanonicalL2BeaconProxyFactoryAddress(uint256 chainId) + public + view + returns (address) + { + return Create2.computeAddress( + _getL2Salt(OrbitSalts.BEACON_PROXY_FACTORY, chainId), + keccak256(type(BeaconProxyFactory).creationCode), + canonicalL2FactoryAddress + ); } - function getCanonicalL2UpgradeExecutorAddress() public view returns (address) { + function getCanonicalL2UpgradeExecutorAddress(uint256 chainId) public view returns (address) { return _getProxyAddress( - _getL2Salt(OrbitSalts.L2_EXECUTOR_LOGIC), _getL2Salt(OrbitSalts.L2_EXECUTOR) + _getL2Salt(OrbitSalts.L2_EXECUTOR_LOGIC, chainId), + _getL2Salt(OrbitSalts.L2_EXECUTOR, chainId), + chainId ); } @@ -632,7 +668,7 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { * @notice L2 contracts are deployed as proxy with dummy seed logic contracts using CREATE2. That enables * us to upfront calculate the expected canonical addresses. */ - function _getProxyAddress(bytes32 logicSalt, bytes32 proxySalt) + function _getProxyAddress(bytes32 logicSalt, bytes32 proxySalt, uint256 chainId) internal view returns (address) @@ -646,7 +682,9 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { keccak256( abi.encodePacked( type(TransparentUpgradeableProxy).creationCode, - abi.encode(logicSeedAddress, canonicalL2ProxyAdminAddress, bytes("")) + abi.encode( + logicSeedAddress, getCanonicalL2ProxyAdminAddress(chainId), bytes("") + ) ) ), canonicalL2FactoryAddress @@ -663,14 +701,16 @@ contract L1AtomicTokenBridgeCreator is Initializable, OwnableUpgradeable { } /** - * @notice Salt for L2 token bridge contracts depends on the caller's address. Canonical token bridge + * @notice Salt for L2 token bridge contracts depends on the chainId and caller's address. Canonical token bridge * will be deployed by retryable ticket which is created by `retryableSender` contract. That * means `retryableSender`'s alias will be used on L2 side to calculate the salt for deploying - * L2 contracts (_getL2Salt function in L2AtomicTokenBridgeFactory). + * L2 contracts, in addition to chainId (_getL2Salt function in L2AtomicTokenBridgeFactory). */ - function _getL2Salt(bytes memory prefix) internal view returns (bytes32) { + function _getL2Salt(bytes memory prefix, uint256 chainId) internal view returns (bytes32) { return keccak256( - abi.encodePacked(prefix, AddressAliasHelper.applyL1ToL2Alias(address(retryableSender))) + abi.encodePacked( + prefix, chainId, AddressAliasHelper.applyL1ToL2Alias(address(retryableSender)) + ) ); } } @@ -682,3 +722,7 @@ interface IERC20Bridge { interface IInbox_ProxyAdmin { function getProxyAdmin() external view returns (address); } + +interface IRollupCore { + function chainId() external view returns (uint256); +} diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index acf7cdfbc8..d692781c2f 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -22,6 +22,8 @@ import { IERC20Bridge__factory, IERC20__factory, ArbMulticall2__factory, + IRollupCore__factory, + IBridge__factory, } from '../build/types' import { abi as UpgradeExecutorABI, @@ -181,28 +183,37 @@ export const createTokenBridge = async ( 'OrbitTokenBridgeCreated' )[0].args + const rollup = await IBridge__factory.connect( + await IInbox__factory.connect(inbox, l1Signer).bridge(), + l1Signer + ).rollup() + const chainId = await IRollupCore__factory.connect(rollup, l1Signer).chainId() + /// pick up L2 contracts - const l2Router = await l1TokenBridgeCreator.getCanonicalL2RouterAddress() + const l2Router = await l1TokenBridgeCreator.getCanonicalL2RouterAddress( + chainId + ) const l2StandardGateway = L2ERC20Gateway__factory.connect( - await l1TokenBridgeCreator.getCanonicalL2StandardGatewayAddress(), + await l1TokenBridgeCreator.getCanonicalL2StandardGatewayAddress(chainId), l2Provider ) const beaconProxyFactory = await l2StandardGateway.beaconProxyFactory() const l2CustomGateway = - await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress() + await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress(chainId) const isUsingFeeToken = feeToken != ethers.constants.AddressZero const l2WethGateway = isUsingFeeToken ? ethers.constants.AddressZero : L2WethGateway__factory.connect( - await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(), + await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(chainId), l2Provider ).address const l1Weth = await l1TokenBridgeCreator.l1Weth() const l2Weth = isUsingFeeToken ? ethers.constants.AddressZero - : await l1TokenBridgeCreator.getCanonicalL2WethAddress() - const l2ProxyAdmin = await l1TokenBridgeCreator.canonicalL2ProxyAdminAddress() + : await l1TokenBridgeCreator.getCanonicalL2WethAddress(chainId) + const l2ProxyAdmin = + await l1TokenBridgeCreator.getCanonicalL2ProxyAdminAddress(chainId) return { l1Router, diff --git a/scripts/goerli-deployment/deployTokenBridgeCreator.ts b/scripts/goerli-deployment/deployTokenBridgeCreator.ts index eb6c1f9b01..46c7abfe0a 100644 --- a/scripts/goerli-deployment/deployTokenBridgeCreator.ts +++ b/scripts/goerli-deployment/deployTokenBridgeCreator.ts @@ -124,7 +124,7 @@ const registerGoerliNetworks = async ( async function main() { // this is just random Orbit rollup that will be used to estimate gas needed to deploy L2 token bridge factory via retryable - const rollupAddress = '0xe16E44efb06F33ed700618A738E24FeFd7801A84' + const rollupAddress = '0x15B318F69107c8122034D07cfcf1787095eF9A89' const { l1TokenBridgeCreator, retryableSender } = await deployTokenBridgeCreator(rollupAddress) console.log('L1TokenBridgeCreator:', l1TokenBridgeCreator.address) diff --git a/test-e2e/tokenBridgeDeploymentTest.ts b/test-e2e/tokenBridgeDeploymentTest.ts index c93531b1f1..2b4e478554 100644 --- a/test-e2e/tokenBridgeDeploymentTest.ts +++ b/test-e2e/tokenBridgeDeploymentTest.ts @@ -4,6 +4,7 @@ import { IERC20Bridge__factory, IInbox__factory, IOwnable__factory, + IRollupCore__factory, L1AtomicTokenBridgeCreator__factory, L1CustomGateway, L1CustomGateway__factory, @@ -460,6 +461,7 @@ async function _getTokenBridgeAddresses( //// L1 // find all the events emitted by this address + const filter: Filter = { address: l1TokenBridgeCreatorAddress, topics: [ @@ -511,27 +513,32 @@ async function _getTokenBridgeAddresses( const usingFeeToken = await isUsingFeeToken(l1.inbox, l1Provider) + const chainId = await IRollupCore__factory.connect( + rollupAddress, + l1Provider + ).chainId() + //// L2 const l2 = { router: ( - await l1TokenBridgeCreator.getCanonicalL2RouterAddress() + await l1TokenBridgeCreator.getCanonicalL2RouterAddress(chainId) ).toLowerCase(), standardGateway: ( - await l1TokenBridgeCreator.getCanonicalL2StandardGatewayAddress() + await l1TokenBridgeCreator.getCanonicalL2StandardGatewayAddress(chainId) ).toLowerCase(), customGateway: ( - await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress() + await l1TokenBridgeCreator.getCanonicalL2CustomGatewayAddress(chainId) ).toLowerCase(), wethGateway: (usingFeeToken ? ethers.constants.AddressZero - : await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress() + : await l1TokenBridgeCreator.getCanonicalL2WethGatewayAddress(chainId) ).toLowerCase(), weth: (usingFeeToken ? ethers.constants.AddressZero - : await l1TokenBridgeCreator.getCanonicalL2WethAddress() + : await l1TokenBridgeCreator.getCanonicalL2WethAddress(chainId) ).toLowerCase(), upgradeExecutor: ( - await l1TokenBridgeCreator.getCanonicalL2UpgradeExecutorAddress() + await l1TokenBridgeCreator.getCanonicalL2UpgradeExecutorAddress(chainId) ).toLowerCase(), } diff --git a/test-foundry/util/TestUtil.sol b/test-foundry/util/TestUtil.sol index 2238b8cb42..27b3265865 100644 --- a/test-foundry/util/TestUtil.sol +++ b/test-foundry/util/TestUtil.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.17; +pragma solidity ^0.8.4; import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; From 9503d3c0ce2d724648602af02e8275c2e2b5959d Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Tue, 12 Sep 2023 15:24:49 +0200 Subject: [PATCH 160/163] Verify all contracts after deployment --- scripts/atomicTokenBridgeDeployer.ts | 108 ++++++++++++++++++ scripts/contractVerifier.ts | 102 +++++++++++++++++ .../deployTokenBridgeCreator.ts | 6 +- 3 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 scripts/contractVerifier.ts diff --git a/scripts/atomicTokenBridgeDeployer.ts b/scripts/atomicTokenBridgeDeployer.ts index d692781c2f..26983ac47c 100644 --- a/scripts/atomicTokenBridgeDeployer.ts +++ b/scripts/atomicTokenBridgeDeployer.ts @@ -38,6 +38,7 @@ import { import { exit } from 'process' import { getBaseFee } from '@arbitrum/sdk/dist/lib/utils/lib' import { RollupAdminLogic__factory } from '@arbitrum/sdk/dist/lib/abi/factories/RollupAdminLogic__factory' +import { ContractVerifier } from './contractVerifier' /** * Use already deployed L1TokenBridgeCreator to create and init token bridge contracts. @@ -397,6 +398,113 @@ export const deployL1TokenBridgeCreator = async ( ) ).wait() + ///// verify contracts + console.log('\n\n Start contract verification \n\n') + const l1Verifier = new ContractVerifier( + (await l1Deployer.provider!.getNetwork()).chainId, + process.env.ARBISCAN_API_KEY! + ) + const abi = ethers.utils.defaultAbiCoder + + await l1Verifier.verifyWithAddress( + 'l1TokenBridgeCreatorProxyAdmin', + l1TokenBridgeCreatorProxyAdmin.address + ) + await l1Verifier.verifyWithAddress( + 'l1TokenBridgeCreatorLogic', + l1TokenBridgeCreatorLogic.address + ) + await l1Verifier.verifyWithAddress( + 'l1TokenBridgeCreatorProxy', + l1TokenBridgeCreatorProxy.address, + abi.encode( + ['address', 'address', 'bytes'], + [ + l1TokenBridgeCreatorLogic.address, + l1TokenBridgeCreatorProxyAdmin.address, + '0x', + ] + ) + ) + await l1Verifier.verifyWithAddress( + 'retryableSenderLogic', + retryableSenderLogic.address + ) + await l1Verifier.verifyWithAddress( + 'retryableSenderProxy', + retryableSenderProxy.address, + abi.encode( + ['address', 'address', 'bytes'], + [ + retryableSenderLogic.address, + l1TokenBridgeCreatorProxyAdmin.address, + '0x', + ] + ) + ) + await l1Verifier.verifyWithAddress('routerTemplate', routerTemplate.address) + await l1Verifier.verifyWithAddress( + 'standardGatewayTemplate', + standardGatewayTemplate.address + ) + await l1Verifier.verifyWithAddress( + 'customGatewayTemplate', + customGatewayTemplate.address + ) + await l1Verifier.verifyWithAddress( + 'wethGatewayTemplate', + wethGatewayTemplate.address + ) + await l1Verifier.verifyWithAddress( + 'feeTokenBasedRouterTemplate', + feeTokenBasedRouterTemplate.address + ) + await l1Verifier.verifyWithAddress( + 'feeTokenBasedStandardGatewayTemplate', + feeTokenBasedStandardGatewayTemplate.address + ) + await l1Verifier.verifyWithAddress( + 'feeTokenBasedCustomGatewayTemplate', + feeTokenBasedCustomGatewayTemplate.address + ) + await l1Verifier.verifyWithAddress( + 'upgradeExecutor', + upgradeExecutor.address, + '', + 20000 + ) + await l1Verifier.verifyWithAddress( + 'l2TokenBridgeFactoryOnL1', + l2TokenBridgeFactoryOnL1.address + ) + await l1Verifier.verifyWithAddress( + 'l2GatewayRouterOnL1', + l2GatewayRouterOnL1.address + ) + await l1Verifier.verifyWithAddress( + 'l2StandardGatewayAddressOnL1', + l2StandardGatewayAddressOnL1.address + ) + await l1Verifier.verifyWithAddress( + 'l2CustomGatewayAddressOnL1', + l2CustomGatewayAddressOnL1.address + ) + await l1Verifier.verifyWithAddress( + 'l2WethGatewayAddressOnL1', + l2WethGatewayAddressOnL1.address + ) + await l1Verifier.verifyWithAddress( + 'l2WethAddressOnL1', + l2WethAddressOnL1.address + ) + await l1Verifier.verifyWithAddress( + 'l2MulticallAddressOnL1', + l2MulticallAddressOnL1.address + ) + + await new Promise(resolve => setTimeout(resolve, 2000)) + console.log('\n\n Contract verification done \n\n') + return { l1TokenBridgeCreator, retryableSender } } diff --git a/scripts/contractVerifier.ts b/scripts/contractVerifier.ts new file mode 100644 index 0000000000..3a5a160569 --- /dev/null +++ b/scripts/contractVerifier.ts @@ -0,0 +1,102 @@ +import { exec } from 'child_process' +import { ethers } from 'ethers' + +export class ContractVerifier { + chainId: number + apiKey: string = '' + + readonly NUM_OF_OPTIMIZATIONS = 100 + readonly COMPILER_VERSION = '0.8.16' + + ///// List of contract addresses and their corresponding source code files + readonly TUP = + 'node_modules/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy' + readonly PROXY_ADMIN = + 'node_modules/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin' + readonly EXECUTOR = + 'node_modules/@offchainlabs/upgrade-executor/src/UpgradeExecutor.sol:UpgradeExecutor' + + readonly contractToSource = { + l1TokenBridgeCreatorProxyAdmin: this.PROXY_ADMIN, + l1TokenBridgeCreatorLogic: + 'contracts/tokenbridge/ethereum/L1AtomicTokenBridgeCreator.sol:L1AtomicTokenBridgeCreator', + l1TokenBridgeCreatorProxy: this.TUP, + retryableSenderLogic: + 'contracts/tokenbridge/ethereum/L1TokenBridgeRetryableSender.sol:L1TokenBridgeRetryableSender', + retryableSenderProxy: this.TUP, + routerTemplate: + 'contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol:L1GatewayRouter', + standardGatewayTemplate: + 'contracts/tokenbridge/ethereum/gateway/L1ERC20Gateway.sol:L1ERC20Gateway', + customGatewayTemplate: + 'contracts/tokenbridge/ethereum/gateway/L1CustomGateway.sol:L1CustomGateway', + wethGatewayTemplate: + 'contracts/tokenbridge/ethereum/gateway/L1WethGateway.sol:L1WethGateway', + feeTokenBasedRouterTemplate: + 'contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol:L1OrbitGatewayRouter', + feeTokenBasedStandardGatewayTemplate: + 'contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol:L1OrbitERC20Gateway', + feeTokenBasedCustomGatewayTemplate: + 'contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol:L1OrbitCustomGateway', + upgradeExecutor: this.EXECUTOR, + l2TokenBridgeFactoryOnL1: + 'contracts/tokenbridge/arbitrum/L2AtomicTokenBridgeFactory.sol:L2AtomicTokenBridgeFactory', + l2GatewayRouterOnL1: + 'contracts/tokenbridge/arbitrum/gateway/L2GatewayRouter.sol:L2GatewayRouter', + l2StandardGatewayAddressOnL1: + 'contracts/tokenbridge/arbitrum/gateway/L2ERC20Gateway.sol:L2ERC20Gateway', + l2CustomGatewayAddressOnL1: + 'contracts/tokenbridge/arbitrum/gateway/L2CustomGateway.sol:L2CustomGateway', + l2WethGatewayAddressOnL1: + 'contracts/tokenbridge/arbitrum/gateway/L2WethGateway.sol:L2WethGateway', + l2WethAddressOnL1: 'contracts/tokenbridge/libraries/aeWETH.sol:aeWETH', + l2MulticallAddressOnL1: 'contracts/rpc-utils/MulticallV2.sol:ArbMulticall2', + } + + constructor(chainId: number, apiKey: string) { + this.chainId = chainId + if (apiKey) { + this.apiKey = apiKey + } + } + + async verifyWithAddress( + name: string, + contractAddress: string, + constructorArgs?: string, + _numOfOptimization?: number + ) { + // avoid rate limiting + await new Promise(resolve => setTimeout(resolve, 1000)) + + let command = `forge verify-contract --chain-id ${this.chainId} --compiler-version ${this.COMPILER_VERSION}` + + if (_numOfOptimization !== undefined) { + command = `${command} --num-of-optimizations ${_numOfOptimization}` + } else { + command = `${command} --num-of-optimizations ${this.NUM_OF_OPTIMIZATIONS}` + } + + const sourceFile = + this.contractToSource[name as keyof typeof this.contractToSource] + + if (constructorArgs) { + command = `${command} --constructor-args ${constructorArgs}` + } + command = `${command} ${contractAddress} ${sourceFile} --etherscan-api-key ${this.apiKey}` + + exec(command, (err: Error | null, stdout: string, stderr: string) => { + console.log('-----------------') + console.log(command) + if (err) { + console.log( + 'Failed to submit for verification', + contractAddress, + stderr + ) + } else { + console.log('Successfully submitted for verification', contractAddress) + } + }) + } +} diff --git a/scripts/goerli-deployment/deployTokenBridgeCreator.ts b/scripts/goerli-deployment/deployTokenBridgeCreator.ts index 46c7abfe0a..cfbd49a2da 100644 --- a/scripts/goerli-deployment/deployTokenBridgeCreator.ts +++ b/scripts/goerli-deployment/deployTokenBridgeCreator.ts @@ -124,11 +124,13 @@ const registerGoerliNetworks = async ( async function main() { // this is just random Orbit rollup that will be used to estimate gas needed to deploy L2 token bridge factory via retryable - const rollupAddress = '0x15B318F69107c8122034D07cfcf1787095eF9A89' + const rollupAddress = '0x8223bd899C6643483872ed2A7b105b2aC9C8aBEc' const { l1TokenBridgeCreator, retryableSender } = await deployTokenBridgeCreator(rollupAddress) + + console.log('Token bridge creator deployed!') console.log('L1TokenBridgeCreator:', l1TokenBridgeCreator.address) - console.log('L1TokenBridgeRetryableSender:', retryableSender.address) + console.log('L1TokenBridgeRetryableSender:', retryableSender.address, '\n') } main().then(() => console.log('Done.')) From e580b9832c029bc5cb411905855d906d19de7b10 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 3 Oct 2023 00:06:03 +0000 Subject: [PATCH 161/163] setGateways() in OrbitGatewayRouter should not be payable This function uses the fee paying token instead of ETH for fees --- contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol index a98797cf31..a7322eba4e 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitGatewayRouter.sol @@ -109,7 +109,7 @@ contract L1OrbitGatewayRouter is L1GatewayRouter { uint256 _gasPriceBid, uint256 _maxSubmissionCost, uint256 _feeAmount - ) external payable onlyOwner returns (uint256) { + ) external onlyOwner returns (uint256) { return _setGateways( _token, From 82c5375bd466f5bb87b9436cac60432d048ff770 Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 5 Oct 2023 15:22:00 +0200 Subject: [PATCH 162/163] Require there is ether sent in erc20 token bridge --- .../tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol | 3 +++ test-foundry/L1ArbitrumExtendedGateway.t.sol | 6 +++--- test-foundry/L1ERC20Gateway.t.sol | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol index cccd209508..ca272641ce 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitERC20Gateway.sol @@ -25,6 +25,9 @@ contract L1OrbitERC20Gateway is L1ERC20Gateway { uint256 _gasPriceBid, bytes calldata _data ) public payable override returns (bytes memory res) { + // fees are paid in native token, so there is no use for ether + require(msg.value == 0, "NO_VALUE"); + // We don't allow bridging of native token to avoid having multiple representations of it // on child chain. Native token can be bridged directly through inbox using depositERC20(). require(_l1Token != _getNativeFeeToken(), "NOT_ALLOWED_TO_BRIDGE_FEE_TOKEN"); diff --git a/test-foundry/L1ArbitrumExtendedGateway.t.sol b/test-foundry/L1ArbitrumExtendedGateway.t.sol index 48b822987f..128e5b86db 100644 --- a/test-foundry/L1ArbitrumExtendedGateway.t.sol +++ b/test-foundry/L1ArbitrumExtendedGateway.t.sol @@ -146,7 +146,7 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { vm.prank(router); vm.expectRevert("EXTRA_DATA_DISABLED"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + l1Gateway.outboundTransferCustomRefund( address(token), user, user, @@ -162,7 +162,7 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { vm.prank(router); vm.expectRevert("L1_NOT_CONTRACT"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + l1Gateway.outboundTransferCustomRefund( address(invalidTokenAddress), user, user, @@ -175,7 +175,7 @@ abstract contract L1ArbitrumExtendedGatewayTest is Test { function test_outboundTransferCustomRefund_revert_NotFromRouter() public { vm.expectRevert("NOT_FROM_ROUTER"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + l1Gateway.outboundTransferCustomRefund( address(token), user, user, diff --git a/test-foundry/L1ERC20Gateway.t.sol b/test-foundry/L1ERC20Gateway.t.sol index 9f9918137b..c6bfb0f7a5 100644 --- a/test-foundry/L1ERC20Gateway.t.sol +++ b/test-foundry/L1ERC20Gateway.t.sol @@ -182,7 +182,7 @@ contract L1ERC20GatewayTest is L1ArbitrumExtendedGatewayTest { vm.prank(router); vm.expectRevert("ERC20: insufficient allowance"); - l1Gateway.outboundTransferCustomRefund{ value: 1 ether }( + l1Gateway.outboundTransferCustomRefund( address(token), user, user, From 044d8d23432b853ded22ffab5c0d11352c31818f Mon Sep 17 00:00:00 2001 From: Goran Vladika Date: Thu, 5 Oct 2023 15:39:21 +0200 Subject: [PATCH 163/163] Make forceRegisterTokenToL2 in L1OrbitCustomGateway non payable --- contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol index 2188a7572d..a1851d886b 100644 --- a/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol +++ b/contracts/tokenbridge/ethereum/gateway/L1OrbitCustomGateway.sol @@ -89,7 +89,7 @@ contract L1OrbitCustomGateway is L1CustomGateway { uint256 _gasPriceBid, uint256 _maxSubmissionCost, uint256 _feeAmount - ) external payable onlyOwner returns (uint256) { + ) external onlyOwner returns (uint256) { return _forceRegisterTokenToL2( _l1Addresses,