diff --git a/.env.example b/.env.example index db67351..b683fcb 100644 --- a/.env.example +++ b/.env.example @@ -25,23 +25,20 @@ ETHERSCAN_API_KEY_OPT= # Bridge/Gateway Deployment # ############################ -# Address of the token to deploy the bridge/gateway for +# Address of the token on L1 to deploy the bridge/gateway for TOKEN= -# Address of the rebasable token to deploy the bridge/gateway for +# Address of the rebasable token on L1 to deploy the bridge/gateway for REBASABLE_TOKEN= -# Address of token rate notifier. Connects Lido core protocol. -TOKEN_RATE_NOTIFIER= - -# Address of token rate pusher +# Address of token rate pusher. Required to config TokenRateOracle. L1_OP_STACK_TOKEN_RATE_PUSHER= # Gas limit required to complete pushing token rate on L2. L2_GAS_LIMIT_FOR_PUSHING_TOKEN_RATE= # A time period when token rate can be considered outdated. -RATE_OUTDATED_DELAY= +RATE_OUTDATED_DELAY=86400 # default is 24 hours # Address of L1 token bridge proxy. L1_TOKEN_BRIDGE= @@ -59,7 +56,7 @@ L2_TOKEN_RATE_ORACLE= GOV_BRIDGE_EXECUTOR= # Name of the network environments used by deployment scripts. -# Might be one of: "mainnet", "goerli". +# Might be one of: "mainnet", "sepolia". NETWORK=mainnet # Run deployment in the forking network instead of public ones diff --git a/README.md b/README.md index 7781dbe..caf32a0 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ To retrieve more detailed info about the bridging process, see the specification - [Lido's Arbitrum Gateway](https://github.com/lidofinance/lido-l2/blob/main/contracts/arbitrum/README.md). - [Lido's Optimism Bridge](https://github.com/lidofinance/lido-l2/blob/main/contracts/optimism/README.md). +- [wstETH Bridging Guide](https://docs.lido.fi/token-guides/wsteth-bridging-guide/#r-5-bridging-l1-lido-dao-decisions) ## Project setup @@ -44,7 +45,15 @@ The configuration of the deployment scripts happens via the ENV variables. The f - [`TOKEN`](#TOKEN) - address of the non-rebasable token to deploy a new bridge on the Ethereum chain. - [`REBASABLE_TOKEN`] (#REBASABLE_TOKEN) - address of the rebasable token to deploy new bridge on the Ethereum chain. -- [`NETWORK`](#NETWORK) - name of the network environments used by deployment scripts. Allowed values: `mainnet`, `goerli`. +- [`L1_OP_STACK_TOKEN_RATE_PUSHER`](#L1_OP_STACK_TOKEN_RATE_PUSHER) - address of token rate pusher. Required to config TokenRateOracle. +- [`L2_GAS_LIMIT_FOR_PUSHING_TOKEN_RATE`](#L2_GAS_LIMIT_FOR_PUSHING_TOKEN_RATE) - gas limit required to complete pushing token rate on L2. +- [`RATE_OUTDATED_DELAY`](#RATE_OUTDATED_DELAY) - a time period when token rate can be considered outdated. Default is 24 hours. +- [`L1_TOKEN_BRIDGE`](#L1_TOKEN_BRIDGE) - address of L1 token bridge. +- [`L2_TOKEN_BRIDGE`](#L2_TOKEN_BRIDGE) - address of L2 token bridge. +- [`L2_TOKEN`](#L2_TOKEN) - address of the non-rebasable token on L2. +- [`L2_TOKEN_RATE_ORACLE`](#L2_TOKEN_RATE_ORACLE) - address of token rate oracle on L2. +- [`GOV_BRIDGE_EXECUTOR`](#GOV_BRIDGE_EXECUTOR) - address of bridge executor. +- [`NETWORK`](#NETWORK) - name of the network environments used by deployment scripts. Allowed values: `mainnet`, `sepolia`. - [`FORKING`](#FORKING) - run deployment in the forking network instead of real ones - [`ETH_DEPLOYER_PRIVATE_KEY`](#ETH_DEPLOYER_PRIVATE_KEY) - The private key of the deployer account in the Ethereum network is used during the deployment process. - [`ARB_DEPLOYER_PRIVATE_KEY`](#ARB_DEPLOYER_PRIVATE_KEY) - The private key of the deployer account in the Arbitrum network is used during the deployment process. @@ -315,17 +324,17 @@ Below variables used in the Arbitrum/Optimism bridge deployment process. #### `TOKEN` -Address of the non-rebasable token to deploy a new bridge on the Ethereum chain. +Address of the existing non-rebasable token to deploy a new bridge for on the Ethereum chain. #### `REBASABLE_TOKEN` -Address of the rebasable token to deploy new bridge on the Ethereum chain. +Address of the existing rebasable token to deploy new bridge for on the Ethereum chain. #### `NETWORK` > Default value: `mainnet` -Name of the network environments used by deployment scripts. Might be one of: `mainnet`, `goerli`. +Name of the network environments used by deployment scripts. Might be one of: `mainnet`, `sepolia`. #### `FORKING` @@ -447,7 +456,7 @@ The following variables are used in the process of the Integration & E2E testing #### `TESTING_ARB_NETWORK` -Name of the network environments used for Arbitrum Integration & E2E testing. Might be one of: `mainnet`, `goerli`. +Name of the network environments used for Arbitrum Integration & E2E testing. Might be one of: `mainnet`, `sepolia`. #### `TESTING_ARB_L1_TOKEN` @@ -487,7 +496,7 @@ Address of the L2 gateway router used in the Acceptance Integration & E2E (when #### `TESTING_OPT_NETWORK` -Name of the network environments used for Optimism Integration & E2E testing. Might be one of: `mainnet`, `goerli`. +Name of the network environments used for Optimism Integration & E2E testing. Might be one of: `mainnet`, `sepolia`. #### `TESTING_OPT_L1_TOKEN` diff --git a/contracts/lib/SignatureChecker.sol b/contracts/lib/SignatureChecker.sol index d42561c..e4e3ab5 100644 --- a/contracts/lib/SignatureChecker.sol +++ b/contracts/lib/SignatureChecker.sol @@ -1,6 +1,6 @@ // SPDX-FileCopyrightText: 2024 OpenZeppelin, Lido // SPDX-License-Identifier: GPL-3.0 -// Writen based on (utils/cryptography/SignatureChecker.sol from d398d68 +// Written based on (utils/cryptography/SignatureChecker.sol from d398d68 pragma solidity 0.8.10; @@ -24,7 +24,6 @@ library SignatureChecker { */ function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) { if (signer.code.length == 0) { - // return true; (address recovered, ECDSA.RecoverError err) = ECDSA.tryRecover(hash, signature); return err == ECDSA.RecoverError.NoError && recovered == signer; } else { diff --git a/contracts/lido/TokenRateNotifier.sol b/contracts/lido/TokenRateNotifier.sol index b9e9e17..28cf18f 100644 --- a/contracts/lido/TokenRateNotifier.sol +++ b/contracts/lido/TokenRateNotifier.sol @@ -3,21 +3,32 @@ pragma solidity 0.8.10; -import {IPostTokenRebaseReceiver} from "./interfaces/IPostTokenRebaseReceiver.sol"; import {ITokenRatePusher} from "./interfaces/ITokenRatePusher.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +/// @notice An interface to subscribe on the `stETH` token rebases (defined in the `Lido` core contract) +interface IPostTokenRebaseReceiver { + + /// @notice Is called in the context of `Lido.handleOracleReport` to notify the subscribers about each token rebase + function handlePostTokenRebase( + uint256 _reportTimestamp, + uint256 _timeElapsed, + uint256 _preTotalShares, + uint256 _preTotalEther, + uint256 _postTotalShares, + uint256 _postTotalEther, + uint256 _sharesMintedAsFees + ) external; +} + /// @author kovalgek /// @notice Notifies all observers when rebase event occures. contract TokenRateNotifier is Ownable, IPostTokenRebaseReceiver { using ERC165Checker for address; /// @notice Maximum amount of observers to be supported. - uint256 public constant MAX_OBSERVERS_COUNT = 16; - - /// @notice Invalid interface id. - bytes4 public constant INVALID_INTERFACE_ID = 0xffffffff; + uint256 public constant MAX_OBSERVERS_COUNT = 32; /// @notice A value that indicates that value was not found. uint256 public constant INDEX_NOT_FOUND = type(uint256).max; @@ -28,6 +39,11 @@ contract TokenRateNotifier is Ownable, IPostTokenRebaseReceiver { /// @notice All observers. address[] public observers; + /// @param initialOwner_ initial owner + constructor(address initialOwner_) { + _transferOwnership(initialOwner_); + } + /// @notice Add a `observer_` to the back of array /// @param observer_ observer address function addObserver(address observer_) external onlyOwner { @@ -55,24 +71,22 @@ contract TokenRateNotifier is Ownable, IPostTokenRebaseReceiver { revert ErrorNoObserverToRemove(); } - for (uint256 obIndex = observerIndexToRemove; obIndex < observers.length - 1; obIndex++) { - observers[obIndex] = observers[obIndex + 1]; - } - + observers[observerIndexToRemove] = observers[observers.length - 1]; observers.pop(); emit ObserverRemoved(observer_); } /// @inheritdoc IPostTokenRebaseReceiver + /// @dev Parameters aren't used because all required data further components fetch by themselves. function handlePostTokenRebase( - uint256, - uint256, - uint256, - uint256, - uint256, - uint256, - uint256 + uint256, /* reportTimestamp */ + uint256, /* timeElapsed */ + uint256, /* preTotalShares */ + uint256, /* preTotalEther */ + uint256, /* postTotalShares */ + uint256, /* postTotalEther */ + uint256 /* sharesMintedAsFees */ ) external { for (uint256 obIndex = 0; obIndex < observers.length; obIndex++) { try ITokenRatePusher(observers[obIndex]).pushTokenRate() {} @@ -93,7 +107,7 @@ contract TokenRateNotifier is Ownable, IPostTokenRebaseReceiver { /// @notice Observer length /// @return Added observers count - function observersLength() public view returns (uint256) { + function observersLength() external view returns (uint256) { return observers.length; } diff --git a/contracts/lido/interfaces/IPostTokenRebaseReceiver.sol b/contracts/lido/interfaces/IPostTokenRebaseReceiver.sol deleted file mode 100644 index 65b1fe9..0000000 --- a/contracts/lido/interfaces/IPostTokenRebaseReceiver.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Lido -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity 0.8.10; - -/// @author kovalgek -/// @notice An interface to subscribe on the `stETH` token rebases (defined in the `Lido` core contract) -interface IPostTokenRebaseReceiver { - - /// @notice Is called in the context of `Lido.handleOracleReport` to notify the subscribers about each token rebase - function handlePostTokenRebase( - uint256 _reportTimestamp, - uint256 _timeElapsed, - uint256 _preTotalShares, - uint256 _preTotalEther, - uint256 _postTotalShares, - uint256 _postTotalEther, - uint256 _sharesMintedAsFees - ) external; -} diff --git a/contracts/lido/interfaces/ITokenRatePusher.sol b/contracts/lido/interfaces/ITokenRatePusher.sol index 9492a24..9d157c3 100644 --- a/contracts/lido/interfaces/ITokenRatePusher.sol +++ b/contracts/lido/interfaces/ITokenRatePusher.sol @@ -4,8 +4,8 @@ pragma solidity 0.8.10; /// @author kovalgek -/// @notice An interface for entity that pushes rate. +/// @notice An interface for entity that pushes token rate. interface ITokenRatePusher { - /// @notice Pushes token rate to L2 by depositing zero tokens. + /// @notice Pushes token rate to L2 by depositing zero token amount. function pushTokenRate() external; } diff --git a/contracts/lido/stubs/OpStackTokenRatePusherWithOutOfGasErrorStub.sol b/contracts/lido/stubs/OpStackTokenRatePusherWithOutOfGasErrorStub.sol index 818b422..cb8d1c2 100644 --- a/contracts/lido/stubs/OpStackTokenRatePusherWithOutOfGasErrorStub.sol +++ b/contracts/lido/stubs/OpStackTokenRatePusherWithOutOfGasErrorStub.sol @@ -8,10 +8,12 @@ import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; contract OpStackTokenRatePusherWithOutOfGasErrorStub is ERC165, ITokenRatePusher { - mapping (uint256 => uint256) data; + uint256 public constant OUT_OF_GAS_INCURRING_MAX = 1000000000000; + + mapping (uint256 => uint256) public data; function pushTokenRate() external { - for (uint256 i = 0; i < 1000000000000; ++i) { + for (uint256 i = 0; i < OUT_OF_GAS_INCURRING_MAX; ++i) { data[i] = i; } } diff --git a/contracts/optimism/DepositDataCodec.sol b/contracts/optimism/DepositDataCodec.sol index 68ada77..5517875 100644 --- a/contracts/optimism/DepositDataCodec.sol +++ b/contracts/optimism/DepositDataCodec.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Lido +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.10; @@ -9,7 +9,7 @@ contract DepositDataCodec { uint8 internal constant RATE_FIELD_SIZE = 12; uint8 internal constant TIMESTAMP_FIELD_SIZE = 5; - + struct DepositData { uint96 rate; uint40 timestamp; @@ -26,11 +26,11 @@ contract DepositDataCodec { } function decodeDepositData(bytes calldata buffer) internal pure returns (DepositData memory) { - + if (buffer.length < RATE_FIELD_SIZE + TIMESTAMP_FIELD_SIZE) { revert ErrorDepositDataLength(); } - + DepositData memory depositData = DepositData({ rate: uint96(bytes12(buffer[0:RATE_FIELD_SIZE])), timestamp: uint40(bytes5(buffer[RATE_FIELD_SIZE:RATE_FIELD_SIZE + TIMESTAMP_FIELD_SIZE])), diff --git a/contracts/optimism/L1ERC20TokenBridge.sol b/contracts/optimism/L1ERC20ExtendedTokensBridge.sol similarity index 98% rename from contracts/optimism/L1ERC20TokenBridge.sol rename to contracts/optimism/L1ERC20ExtendedTokensBridge.sol index 087df07..7e303a9 100644 --- a/contracts/optimism/L1ERC20TokenBridge.sol +++ b/contracts/optimism/L1ERC20ExtendedTokensBridge.sol @@ -20,7 +20,7 @@ import {IERC20WstETH} from "../token/interfaces/IERC20WstETH.sol"; /// @notice The L1 ERC20 token bridge locks bridged tokens on the L1 side, sends deposit messages /// on the L2 side, and finalizes token withdrawals from L2. Additionally, adds the methods for /// bridging management: enabling and disabling withdrawals/deposits -abstract contract L1ERC20TokenBridge is +abstract contract L1ERC20ExtendedTokensBridge is IL1ERC20Bridge, BridgingManager, RebasableAndNonRebasableTokens, @@ -44,7 +44,12 @@ abstract contract L1ERC20TokenBridge is address l1TokenRebasable_, address l2TokenNonRebasable_, address l2TokenRebasable_ - ) CrossDomainEnabled(messenger_) RebasableAndNonRebasableTokens(l1TokenNonRebasable_, l1TokenRebasable_, l2TokenNonRebasable_, l2TokenRebasable_) { + ) CrossDomainEnabled(messenger_) RebasableAndNonRebasableTokens( + l1TokenNonRebasable_, + l1TokenRebasable_, + l2TokenNonRebasable_, + l2TokenRebasable_ + ) { L2_TOKEN_BRIDGE = l2TokenBridge_; } diff --git a/contracts/optimism/L1LidoTokensBridge.sol b/contracts/optimism/L1LidoTokensBridge.sol index cd144d1..491ff28 100644 --- a/contracts/optimism/L1LidoTokensBridge.sol +++ b/contracts/optimism/L1LidoTokensBridge.sol @@ -3,12 +3,12 @@ pragma solidity 0.8.10; -import {L1ERC20TokenBridge} from "./L1ERC20TokenBridge.sol"; +import {L1ERC20ExtendedTokensBridge} from "./L1ERC20ExtendedTokensBridge.sol"; import {IERC20WstETH} from "../token/interfaces/IERC20WstETH.sol"; /// @author kovalgek -/// @notice Hides wstETH concept from other contracts to keep `L1ERC20TokenBridge` reusable. -contract L1LidoTokensBridge is L1ERC20TokenBridge { +/// @notice Hides wstETH concept from other contracts to keep `L1ERC20ExtendedTokensBridge` reusable. +contract L1LidoTokensBridge is L1ERC20ExtendedTokensBridge { constructor( address messenger_, @@ -17,7 +17,7 @@ contract L1LidoTokensBridge is L1ERC20TokenBridge { address l1TokenRebasable_, address l2TokenNonRebasable_, address l2TokenRebasable_ - ) L1ERC20TokenBridge( + ) L1ERC20ExtendedTokensBridge( messenger_, l2TokenBridge_, l1TokenNonRebasable_, diff --git a/contracts/optimism/L2ERC20TokenBridge.sol b/contracts/optimism/L2ERC20ExtendedTokensBridge.sol similarity index 97% rename from contracts/optimism/L2ERC20TokenBridge.sol rename to contracts/optimism/L2ERC20ExtendedTokensBridge.sol index dd01601..f2b630b 100644 --- a/contracts/optimism/L2ERC20TokenBridge.sol +++ b/contracts/optimism/L2ERC20ExtendedTokensBridge.sol @@ -24,7 +24,7 @@ import {DepositDataCodec} from "./DepositDataCodec.sol"; /// deposits into the L1 token bridge. It also acts as a burner of the tokens /// intended for withdrawal, informing the L1 bridge to release L1 funds. Additionally, adds /// the methods for bridging management: enabling and disabling withdrawals/deposits -contract L2ERC20TokenBridge is +contract L2ERC20ExtendedTokensBridge is IL2ERC20Bridge, BridgingManager, RebasableAndNonRebasableTokens, @@ -48,7 +48,12 @@ contract L2ERC20TokenBridge is address l1TokenRebasable_, address l2TokenNonRebasable_, address l2TokenRebasable_ - ) CrossDomainEnabled(messenger_) RebasableAndNonRebasableTokens(l1TokenNonRebasable_, l1TokenRebasable_, l2TokenNonRebasable_, l2TokenRebasable_) { + ) CrossDomainEnabled(messenger_) RebasableAndNonRebasableTokens( + l1TokenNonRebasable_, + l1TokenRebasable_, + l2TokenNonRebasable_, + l2TokenRebasable_ + ) { L1_TOKEN_BRIDGE = l1TokenBridge_; } @@ -95,6 +100,7 @@ contract L2ERC20TokenBridge is { if (_isRebasableTokenFlow(l1Token_, l2Token_)) { DepositData memory depositData = decodeDepositData(data_); + ITokenRateOracle tokenRateOracle = ERC20Rebasable(L2_TOKEN_REBASABLE).TOKEN_RATE_ORACLE(); tokenRateOracle.updateRate(depositData.rate, depositData.timestamp); diff --git a/contracts/optimism/README.md b/contracts/optimism/README.md index 954556d..c493349 100644 --- a/contracts/optimism/README.md +++ b/contracts/optimism/README.md @@ -41,8 +41,8 @@ A high-level overview of the proposed solution might be found in the below diagr - [**`BridgingManager`**](#BridgingManager) - contains administrative methods to retrieve and control the state of the bridging process. - [**`BridgeableTokens`**](#BridgeableTokens) - contains the logic for validation of tokens used in the bridging process. - [**`CrossDomainEnabled`**](#CrossDomainEnabled) - helper contract for contracts performing cross-domain communications -- [**`L1ERC20TokenBridge`**](#L1ERC20TokenBridge) - Ethereum's counterpart of the bridge to bridge registered ERC20 compatible tokens between Ethereum and Optimism chains. -- [**`L2ERC20TokenBridge`**](#L2ERC20TokenBridge) - Optimism's counterpart of the bridge to bridge registered ERC20 compatible tokens between Ethereum and Optimism chains +- [**`L1ERC20ExtendedTokensBridge`**](#L1ERC20ExtendedTokensBridge) - Ethereum's counterpart of the bridge to bridge registered ERC20 compatible tokens between Ethereum and Optimism chains. +- [**`L2ERC20ExtendedTokensBridge`**](#L2ERC20ExtendedTokensBridge) - Optimism's counterpart of the bridge to bridge registered ERC20 compatible tokens between Ethereum and Optimism chains - [**`ERC20Bridged`**](#ERC20Bridged) - an implementation of the `ERC20` token with administrative methods to mint and burn tokens. - [**`OssifiableProxy`**](#OssifiableProxy) - the ERC1967 proxy with extra admin functionality. @@ -216,7 +216,7 @@ Sends a message to an account on another domain. Enforces that the modified function is only callable by a specific cross-domain account. -## `L1ERC20TokenBridge` +## `L1ERC20ExtendedTokensBridge` **Implements:** [`IL1ERC20Bridge`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/IL1ERC20Bridge.sol) **Inherits:** [`BridgingManager`](#BridgingManager) [`BridgeableTokens`](#BridgeableTokens) [`CrossDomainEnabled`](#CrossDomainEnabled) @@ -300,7 +300,7 @@ Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance Performs the logic for deposits by informing the L2 Deposited Token contract of the deposit and calling safeTransferFrom to lock the L1 funds. -## `L2ERC20TokenBridge` +## `L2ERC20ExtendedTokensBridge` **Implements:** [`IL2ERC20Bridge`](https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/IL2ERC20Bridge.sol) **Extends** [`BridgingManager`](#BridgingManager) [`BridgeableTokens`](#BridgeableTokens) [`CrossDomainEnabled`](#CrossDomainEnabled) @@ -661,7 +661,7 @@ Validates that that proxy is not ossified and that method is called by the admin ## Deployment Process -To reduce the gas costs for users, contracts `L1ERC20TokenBridge`, `L2ERC20TokenBridge`, and `ERC20Bridged` contracts use immutable variables as much as possible. But some of those variables are cross-referred. For example, `L1ERC20TokenBridge` has reference to `L2ERC20TokenBridge` and vice versa. As we use proxies, we can deploy proxies at first and stub the implementation with an empty contract. Then deploy actual implementations with addresses of deployed proxies and then upgrade proxies with new implementations. For stub, the following contract might be used: +To reduce the gas costs for users, contracts `L1ERC20ExtendedTokensBridge`, `L2ERC20ExtendedTokensBridge`, and `ERC20Bridged` contracts use immutable variables as much as possible. But some of those variables are cross-referred. For example, `L1ERC20ExtendedTokensBridge` has reference to `L2ERC20ExtendedTokensBridge` and vice versa. As we use proxies, we can deploy proxies at first and stub the implementation with an empty contract. Then deploy actual implementations with addresses of deployed proxies and then upgrade proxies with new implementations. For stub, the following contract might be used: ``` pragma solidity ^0.8.0; @@ -676,7 +676,7 @@ As an additional link in the tokens flow chain, the Optimism protocol and bridge ## Minting of uncollateralized L2 token -Such an attack might happen if an attacker obtains the right to call `L2ERC20TokenBridge.finalizeDeposit()` directly. In such a scenario, an attacker can mint uncollaterized tokens on L2 and initiate withdrawal later. +Such an attack might happen if an attacker obtains the right to call `L2ERC20ExtendedTokensBridge.finalizeDeposit()` directly. In such a scenario, an attacker can mint uncollaterized tokens on L2 and initiate withdrawal later. The best way to detect such an attack is an offchain monitoring of the minting and depositing/withdrawal events. Based on such events might be tracked following stats: diff --git a/contracts/token/interfaces/IERC20TokenRate.sol b/contracts/token/interfaces/IERC20TokenRate.sol index 16c5187..0b57716 100644 --- a/contracts/token/interfaces/IERC20TokenRate.sol +++ b/contracts/token/interfaces/IERC20TokenRate.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Lido +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.10; diff --git a/contracts/token/interfaces/IERC20Wrapper.sol b/contracts/token/interfaces/IERC20Wrapper.sol index 6b3125d..c443f3c 100644 --- a/contracts/token/interfaces/IERC20Wrapper.sol +++ b/contracts/token/interfaces/IERC20Wrapper.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Lido +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.10; diff --git a/contracts/token/interfaces/ITokenRateOracle.sol b/contracts/token/interfaces/ITokenRateOracle.sol index 2f2d32f..ce057ac 100644 --- a/contracts/token/interfaces/ITokenRateOracle.sol +++ b/contracts/token/interfaces/ITokenRateOracle.sol @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 Lido +// SPDX-FileCopyrightText: 2024 Lido // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.10; @@ -10,7 +10,7 @@ interface ITokenRateOracle { /// @notice get the latest token rate data. /// @return roundId_ is a unique id for each answer. The value is based on timestamp. /// @return answer_ is wstETH/stETH token rate. - /// @return startedAt_ is time when rate was pushed on L1 side. + /// @return startedAt_ is time when rate was pushed on L1 side. /// @return updatedAt_ is the same as startedAt_. /// @return answeredInRound_ is the same as roundId_. function latestRoundData() @@ -34,6 +34,6 @@ interface ITokenRateOracle { /// @notice Updates token rate. /// @param tokenRate_ wstETH/stETH token rate. - /// @param rateL1Timestamp_ L1 time when rate was pushed on L1 side. + /// @param rateL1Timestamp_ L1 time when rate was pushed on L1 side. function updateRate(uint256 tokenRate_, uint256 rateL1Timestamp_) external; -} \ No newline at end of file +} diff --git a/scripts/optimism/deploy-bridge.ts b/scripts/optimism/deploy-bridge.ts index 2e4f272..57538f4 100644 --- a/scripts/optimism/deploy-bridge.ts +++ b/scripts/optimism/deploy-bridge.ts @@ -59,16 +59,16 @@ async function main() { await l1DeployScript.run(); await l2DeployScript.run(); - const l1ERC20TokenBridgeProxyDeployStepIndex = 1; + const l1ERC20ExtendedTokensBridgeProxyDeployStepIndex = 1; const l1BridgingManagement = new BridgingManagement( - l1DeployScript.getContractAddress(l1ERC20TokenBridgeProxyDeployStepIndex), + l1DeployScript.getContractAddress(l1ERC20ExtendedTokensBridgeProxyDeployStepIndex), ethDeployer, { logger: console } ); - const l2ERC20TokenBridgeProxyDeployStepIndex = 5; + const l2ERC20ExtendedTokensBridgeProxyDeployStepIndex = 5; const l2BridgingManagement = new BridgingManagement( - l2DeployScript.getContractAddress(l2ERC20TokenBridgeProxyDeployStepIndex), + l2DeployScript.getContractAddress(l2ERC20ExtendedTokensBridgeProxyDeployStepIndex), optDeployer, { logger: console } ); diff --git a/test/arbitrum/_launch.test.ts b/test/arbitrum/_launch.test.ts index e571136..504fdde 100644 --- a/test/arbitrum/_launch.test.ts +++ b/test/arbitrum/_launch.test.ts @@ -2,7 +2,7 @@ import { assert } from "chai"; import env from "../../utils/env"; import arbitrum from "../../utils/arbitrum"; -import { L1ERC20TokenBridge__factory } from "../../typechain"; +import { L1ERC20ExtendedTokensBridge__factory } from "../../typechain"; import { wei } from "../../utils/wei"; import testing, { scenario } from "../../utils/testing"; import { BridgingManagerRole } from "../../utils/bridging-management"; @@ -71,7 +71,7 @@ async function ctx() { wei.toBigNumber(wei`1 ether`) ); - const l1ERC20TokenGatewayImpl = L1ERC20TokenBridge__factory.connect( + const l1ERC20TokenGatewayImpl = L1ERC20ExtendedTokensBridge__factory.connect( l1ERC20TokenGateway.address, l1DevMultisig ); diff --git a/test/bridge-executor/optimism.integration.test.ts b/test/bridge-executor/optimism.integration.test.ts index bc8fcc1..ee290cb 100644 --- a/test/bridge-executor/optimism.integration.test.ts +++ b/test/bridge-executor/optimism.integration.test.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; import { ERC20BridgedStub__factory, - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, OssifiableProxy__factory, OptimismBridgeExecutor__factory, ERC20Bridged__factory, @@ -19,23 +19,23 @@ import deploymentAll from "../../utils/optimism/deploymentAllFromScratch"; scenario("Optimism :: Bridge Executor integration test", ctxFactory) .step("Activate L2 bridge", async (ctx) => { - const { l2ERC20TokenBridge, bridgeExecutor, l2CrossDomainMessenger } = + const { l2ERC20ExtendedTokensBridge, bridgeExecutor, l2CrossDomainMessenger } = ctx.l2; assert.isFalse( - await l2ERC20TokenBridge.hasRole( + await l2ERC20ExtendedTokensBridge.hasRole( BridgingManagerRole.DEPOSITS_ENABLER_ROLE.hash, bridgeExecutor.address ) ); assert.isFalse( - await l2ERC20TokenBridge.hasRole( + await l2ERC20ExtendedTokensBridge.hasRole( BridgingManagerRole.WITHDRAWALS_ENABLER_ROLE.hash, bridgeExecutor.address ) ); - assert.isFalse(await l2ERC20TokenBridge.isDepositsEnabled()); - assert.isFalse(await l2ERC20TokenBridge.isWithdrawalsEnabled()); + assert.isFalse(await l2ERC20ExtendedTokensBridge.isDepositsEnabled()); + assert.isFalse(await l2ERC20ExtendedTokensBridge.isWithdrawalsEnabled()); const actionsSetCountBefore = await bridgeExecutor.getActionsSetCount(); @@ -46,7 +46,7 @@ scenario("Optimism :: Bridge Executor integration test", ctxFactory) 0, 300_000, bridgeExecutor.interface.encodeFunctionData("queue", [ - new Array(4).fill(l2ERC20TokenBridge.address), + new Array(4).fill(l2ERC20ExtendedTokensBridge.address), new Array(4).fill(0), [ "grantRole(bytes32,address)", @@ -56,25 +56,25 @@ scenario("Optimism :: Bridge Executor integration test", ctxFactory) ], [ "0x" + - l2ERC20TokenBridge.interface + l2ERC20ExtendedTokensBridge.interface .encodeFunctionData("grantRole", [ BridgingManagerRole.DEPOSITS_ENABLER_ROLE.hash, bridgeExecutor.address, ]) .substring(10), "0x" + - l2ERC20TokenBridge.interface + l2ERC20ExtendedTokensBridge.interface .encodeFunctionData("grantRole", [ BridgingManagerRole.WITHDRAWALS_ENABLER_ROLE.hash, bridgeExecutor.address, ]) .substring(10), "0x" + - l2ERC20TokenBridge.interface + l2ERC20ExtendedTokensBridge.interface .encodeFunctionData("enableDeposits") .substring(10), "0x" + - l2ERC20TokenBridge.interface + l2ERC20ExtendedTokensBridge.interface .encodeFunctionData("enableWithdrawals") .substring(10), ], @@ -91,33 +91,33 @@ scenario("Optimism :: Bridge Executor integration test", ctxFactory) await bridgeExecutor.execute(actionsSetCountAfter.sub(1), { value: 0 }); assert.isTrue( - await l2ERC20TokenBridge.hasRole( + await l2ERC20ExtendedTokensBridge.hasRole( BridgingManagerRole.DEPOSITS_ENABLER_ROLE.hash, bridgeExecutor.address ) ); assert.isTrue( - await l2ERC20TokenBridge.hasRole( + await l2ERC20ExtendedTokensBridge.hasRole( BridgingManagerRole.WITHDRAWALS_ENABLER_ROLE.hash, bridgeExecutor.address ) ); - assert.isTrue(await l2ERC20TokenBridge.isDepositsEnabled()); - assert.isTrue(await l2ERC20TokenBridge.isWithdrawalsEnabled()); + assert.isTrue(await l2ERC20ExtendedTokensBridge.isDepositsEnabled()); + assert.isTrue(await l2ERC20ExtendedTokensBridge.isWithdrawalsEnabled()); }) .step("Change Proxy implementation", async (ctx) => { const { l2Token, l2CrossDomainMessenger, - l2ERC20TokenBridgeProxy, + l2ERC20ExtendedTokensBridgeProxy, bridgeExecutor, } = ctx.l2; const actionsSetCountBefore = await bridgeExecutor.getActionsSetCount(); const proxyImplBefore = - await l2ERC20TokenBridgeProxy.proxy__getImplementation(); + await l2ERC20ExtendedTokensBridgeProxy.proxy__getImplementation(); await l2CrossDomainMessenger.relayMessage( 0, @@ -126,12 +126,12 @@ scenario("Optimism :: Bridge Executor integration test", ctxFactory) 0, 300_000, bridgeExecutor.interface.encodeFunctionData("queue", [ - [l2ERC20TokenBridgeProxy.address], + [l2ERC20ExtendedTokensBridgeProxy.address], [0], ["proxy__upgradeTo(address)"], [ "0x" + - l2ERC20TokenBridgeProxy.interface + l2ERC20ExtendedTokensBridgeProxy.interface .encodeFunctionData("proxy__upgradeTo", [l2Token.address]) .substring(10), ], @@ -145,7 +145,7 @@ scenario("Optimism :: Bridge Executor integration test", ctxFactory) await bridgeExecutor.execute(actionsSetCountBefore, { value: 0 }); const proxyImplAfter = - await l2ERC20TokenBridgeProxy.proxy__getImplementation(); + await l2ERC20ExtendedTokensBridgeProxy.proxy__getImplementation(); assert.notEqual(proxyImplBefore, proxyImplAfter); assert.equal(proxyImplAfter, l2Token.address); @@ -154,14 +154,14 @@ scenario("Optimism :: Bridge Executor integration test", ctxFactory) .step("Change proxy Admin", async (ctx) => { const { l2CrossDomainMessenger, - l2ERC20TokenBridgeProxy, + l2ERC20ExtendedTokensBridgeProxy, bridgeExecutor, accounts: { sender }, } = ctx.l2; const actionsSetCountBefore = await bridgeExecutor.getActionsSetCount(); - const proxyAdminBefore = await l2ERC20TokenBridgeProxy.proxy__getAdmin(); + const proxyAdminBefore = await l2ERC20ExtendedTokensBridgeProxy.proxy__getAdmin(); await l2CrossDomainMessenger.relayMessage( 0, @@ -170,12 +170,12 @@ scenario("Optimism :: Bridge Executor integration test", ctxFactory) 0, 300_000, bridgeExecutor.interface.encodeFunctionData("queue", [ - [l2ERC20TokenBridgeProxy.address], + [l2ERC20ExtendedTokensBridgeProxy.address], [0], ["proxy__changeAdmin(address)"], [ "0x" + - l2ERC20TokenBridgeProxy.interface + l2ERC20ExtendedTokensBridgeProxy.interface .encodeFunctionData("proxy__changeAdmin", [sender.address]) .substring(10), ], @@ -188,7 +188,7 @@ scenario("Optimism :: Bridge Executor integration test", ctxFactory) assert.equalBN(actionsSetCountBefore.add(1), actionSetCount); await bridgeExecutor.execute(actionsSetCountBefore, { value: 0 }); - const proxyAdminAfter = await l2ERC20TokenBridgeProxy.proxy__getAdmin(); + const proxyAdminAfter = await l2ERC20ExtendedTokensBridgeProxy.proxy__getAdmin(); assert.notEqual(proxyAdminBefore, proxyAdminAfter); assert.equal(proxyAdminAfter, sender.address); @@ -266,11 +266,11 @@ async function ctxFactory() { optDeployScript.tokenProxyAddress, l2Deployer ); - const l2ERC20TokenBridge = L2ERC20TokenBridge__factory.connect( + const l2ERC20ExtendedTokensBridge = L2ERC20ExtendedTokensBridge__factory.connect( optDeployScript.tokenBridgeProxyAddress, l2Deployer ); - const l2ERC20TokenBridgeProxy = OssifiableProxy__factory.connect( + const l2ERC20ExtendedTokensBridgeProxy = OssifiableProxy__factory.connect( optDeployScript.tokenBridgeProxyAddress, l2Deployer ); @@ -305,9 +305,9 @@ async function ctxFactory() { l2: { l2Token, bridgeExecutor: govBridgeExecutor.connect(l2Deployer), - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, l2CrossDomainMessenger, - l2ERC20TokenBridgeProxy, + l2ERC20ExtendedTokensBridgeProxy, accounts: { sender: testing.accounts.sender(l2Provider), admin: l2Deployer, diff --git a/test/optimism/L1ERC20TokenBridge.unit.test.ts b/test/optimism/L1ERC20TokenBridge.unit.test.ts index efafeb5..d70705d 100644 --- a/test/optimism/L1ERC20TokenBridge.unit.test.ts +++ b/test/optimism/L1ERC20TokenBridge.unit.test.ts @@ -4,7 +4,7 @@ import { ERC20BridgedStub__factory, ERC20WrapperStub__factory, L1LidoTokensBridge__factory, - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, OssifiableProxy__factory, EmptyContractStub__factory, } from "../../typechain"; @@ -160,7 +160,7 @@ unit("Optimism :: L1LidoTokensBridge", ctxFactory) await assert.emits(l1Messenger, tx, "SentMessage", [ l2TokenBridgeEOA.address, l1TokenBridge.address, - L2ERC20TokenBridge__factory.createInterface().encodeFunctionData( + L2ERC20ExtendedTokensBridge__factory.createInterface().encodeFunctionData( "finalizeDeposit", [ l1TokenNonRebasable.address, @@ -229,7 +229,7 @@ unit("Optimism :: L1LidoTokensBridge", ctxFactory) await assert.emits(l1Messenger, tx, "SentMessage", [ l2TokenBridgeEOA.address, l1TokenBridge.address, - L2ERC20TokenBridge__factory.createInterface().encodeFunctionData( + L2ERC20ExtendedTokensBridge__factory.createInterface().encodeFunctionData( "finalizeDeposit", [ l1TokenRebasable.address, @@ -425,7 +425,7 @@ unit("Optimism :: L1LidoTokensBridge", ctxFactory) await assert.emits(l1Messenger, tx, "SentMessage", [ l2TokenBridgeEOA.address, l1TokenBridge.address, - L2ERC20TokenBridge__factory.createInterface().encodeFunctionData( + L2ERC20ExtendedTokensBridge__factory.createInterface().encodeFunctionData( "finalizeDeposit", [ l1TokenNonRebasable.address, @@ -497,7 +497,7 @@ unit("Optimism :: L1LidoTokensBridge", ctxFactory) await assert.emits(l1Messenger, tx, "SentMessage", [ l2TokenBridgeEOA.address, l1TokenBridge.address, - L2ERC20TokenBridge__factory.createInterface().encodeFunctionData( + L2ERC20ExtendedTokensBridge__factory.createInterface().encodeFunctionData( "finalizeDeposit", [ l1TokenRebasable.address, diff --git a/test/optimism/L2ERC20TokenBridge.unit.test.ts b/test/optimism/L2ERC20TokenBridge.unit.test.ts index 1fd77dd..5ea2dc6 100644 --- a/test/optimism/L2ERC20TokenBridge.unit.test.ts +++ b/test/optimism/L2ERC20TokenBridge.unit.test.ts @@ -5,7 +5,7 @@ import { TokenRateOracle__factory, ERC20Rebasable__factory, L1LidoTokensBridge__factory, - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, OssifiableProxy__factory, EmptyContractStub__factory, CrossDomainMessengerStub__factory, @@ -18,7 +18,7 @@ import { getContractAddress } from "ethers/lib/utils"; import { JsonRpcProvider } from "@ethersproject/providers"; import { BigNumber } from "ethers"; -unit("Optimism:: L2ERC20TokenBridge", ctxFactory) +unit("Optimism:: L2ERC20ExtendedTokensBridge", ctxFactory) .test("l1TokenBridge()", async (ctx) => { assert.equal( await ctx.l2TokenBridge.l1TokenBridge(), @@ -727,7 +727,7 @@ async function ctxFactory() { l2TokenBridgeProxyAddress ); - const l2TokenBridgeImpl = await new L2ERC20TokenBridge__factory( + const l2TokenBridgeImpl = await new L2ERC20ExtendedTokensBridge__factory( deployer ).deploy( l2MessengerStub.address, @@ -748,7 +748,7 @@ async function ctxFactory() { ]) ); - const l2TokenBridge = L2ERC20TokenBridge__factory.connect( + const l2TokenBridge = L2ERC20ExtendedTokensBridge__factory.connect( l2TokenBridgeProxy.address, deployer ); diff --git a/test/optimism/TokenRateNotifier.unit.test.ts b/test/optimism/TokenRateNotifier.unit.test.ts index 1499772..d8ca1bc 100644 --- a/test/optimism/TokenRateNotifier.unit.test.ts +++ b/test/optimism/TokenRateNotifier.unit.test.ts @@ -17,204 +17,225 @@ import { unit("TokenRateNotifier", ctxFactory) - .test("initial state", async (ctx) => { - const { tokenRateNotifier } = ctx.contracts; - - assert.equalBN(await tokenRateNotifier.MAX_OBSERVERS_COUNT(), 16); - assert.equal(await tokenRateNotifier.INVALID_INTERFACE_ID(), "0xffffffff"); - const iTokenRateObserver = getInterfaceID(ITokenRatePusher__factory.createInterface()); - assert.equal(await tokenRateNotifier.REQUIRED_INTERFACE(), iTokenRateObserver._hex); - assert.equalBN(await tokenRateNotifier.observersLength(), 0); - }) - - .test("addObserver() :: not the owner", async (ctx) => { - const { tokenRateNotifier } = ctx.contracts; - const { stranger } = ctx.accounts; - - await assert.revertsWith( - tokenRateNotifier - .connect(stranger) - .addObserver(ethers.constants.AddressZero), - "Ownable: caller is not the owner" - ); - }) - - .test("addObserver() :: revert on adding zero address observer", async (ctx) => { - const { tokenRateNotifier } = ctx.contracts; - - await assert.revertsWith( - tokenRateNotifier.addObserver(ethers.constants.AddressZero), - "ErrorZeroAddressObserver()" - ); - }) - - .test("addObserver() :: revert on adding observer with bad interface", async (ctx) => { - const { tokenRateNotifier } = ctx.contracts; - const { deployer } = ctx.accounts; - - const observer = await new TokenRateNotifier__factory(deployer).deploy(); - await assert.revertsWith( - tokenRateNotifier.addObserver(observer.address), - "ErrorBadObserverInterface()" - ); - }) - - .test("addObserver() :: revert on adding too many observers", async (ctx) => { - const { tokenRateNotifier, opStackTokenRatePusher } = ctx.contracts; - - assert.equalBN(await tokenRateNotifier.observersLength(), 0); - const maxObservers = await tokenRateNotifier.MAX_OBSERVERS_COUNT(); - for (let i = 0; i < maxObservers.toNumber(); i++) { - await tokenRateNotifier.addObserver(opStackTokenRatePusher.address); - } - assert.equalBN(await tokenRateNotifier.observersLength(), maxObservers); - - await assert.revertsWith( - tokenRateNotifier.addObserver(opStackTokenRatePusher.address), - "ErrorMaxObserversCountExceeded()" - ); - }) - - .test("addObserver() :: happy path of adding observer", async (ctx) => { - const { tokenRateNotifier, opStackTokenRatePusher } = ctx.contracts; - - assert.equalBN(await tokenRateNotifier.observersLength(), 0); - const tx = await tokenRateNotifier.addObserver(opStackTokenRatePusher.address); - assert.equalBN(await tokenRateNotifier.observersLength(), 1); - - await assert.emits(tokenRateNotifier, tx, "ObserverAdded", [opStackTokenRatePusher.address]); - }) - - .test("removeObserver() :: revert on calling by not the owner", async (ctx) => { - const { tokenRateNotifier } = ctx.contracts; - const { stranger } = ctx.accounts; - - await assert.revertsWith( - tokenRateNotifier - .connect(stranger) - .removeObserver(ethers.constants.AddressZero), - "Ownable: caller is not the owner" - ); - }) - - .test("removeObserver() :: revert on removing non-added observer", async (ctx) => { - const { tokenRateNotifier, opStackTokenRatePusher } = ctx.contracts; - - assert.equalBN(await tokenRateNotifier.observersLength(), 0); - - await assert.revertsWith( - tokenRateNotifier.removeObserver(opStackTokenRatePusher.address), - "ErrorNoObserverToRemove()" - ); - }) - - .test("removeObserver() :: happy path of removing observer", async (ctx) => { - const { tokenRateNotifier, opStackTokenRatePusher } = ctx.contracts; - - assert.equalBN(await tokenRateNotifier.observersLength(), 0); - - await tokenRateNotifier.addObserver(opStackTokenRatePusher.address); - - assert.equalBN(await tokenRateNotifier.observersLength(), 1); - - const tx = await tokenRateNotifier.removeObserver(opStackTokenRatePusher.address); - await assert.emits(tokenRateNotifier, tx, "ObserverRemoved", [opStackTokenRatePusher.address]); - - assert.equalBN(await tokenRateNotifier.observersLength(), 0); - }) - - .test("handlePostTokenRebase() :: failed with some error", async (ctx) => { - const { tokenRateNotifier } = ctx.contracts; - const { deployer } = ctx.accounts; - - const observer = await new OpStackTokenRatePusherWithSomeErrorStub__factory(deployer).deploy(); - await tokenRateNotifier.addObserver(observer.address); - - const tx = await tokenRateNotifier.handlePostTokenRebase(1,2,3,4,5,6,7); - - await assert.emits(tokenRateNotifier, tx, "PushTokenRateFailed", [observer.address, "0x332e27d2"]); - }) - - .test("handlePostTokenRebase() :: revert when observer has out of gas error", async (ctx) => { - const { tokenRateNotifier } = ctx.contracts; - const { deployer } = ctx.accounts; - - const observer = await new OpStackTokenRatePusherWithOutOfGasErrorStub__factory(deployer).deploy(); - await tokenRateNotifier.addObserver(observer.address); - - await assert.revertsWith( - tokenRateNotifier.handlePostTokenRebase(1,2,3,4,5,6,7), - "ErrorTokenRateNotifierRevertedWithNoData()" - ); - }) - - .test("handlePostTokenRebase() :: happy path of handling token rebase", async (ctx) => { - const { - tokenRateNotifier, - l1MessengerStub, - opStackTokenRatePusher, - l1TokenNonRebasableStub - } = ctx.contracts; - const { tokenRateOracle } = ctx.accounts; - const { l2GasLimitForPushingTokenRate } = ctx.constants; - - let tokenRate = await l1TokenNonRebasableStub.stEthPerToken(); - await tokenRateNotifier.addObserver(opStackTokenRatePusher.address); - let tx = await tokenRateNotifier.handlePostTokenRebase(1,2,3,4,5,6,7); - - const provider = await ethers.provider; - const blockNumber = await provider.getBlockNumber(); - const blockTimestamp = (await provider.getBlock(blockNumber)).timestamp; - - await assert.emits(l1MessengerStub, tx, "SentMessage", [ - tokenRateOracle.address, - opStackTokenRatePusher.address, - ITokenRateOracle__factory.createInterface().encodeFunctionData( - "updateRate", - [ - tokenRate, - blockTimestamp - ] - ), - 1, - l2GasLimitForPushingTokenRate, - ]); - }) - - .run(); + .test("initial state", async (ctx) => { + const { tokenRateNotifier } = ctx.contracts; + + assert.equalBN(await tokenRateNotifier.MAX_OBSERVERS_COUNT(), 32); + const iTokenRateObserver = getInterfaceID(ITokenRatePusher__factory.createInterface()); + assert.equal(await tokenRateNotifier.REQUIRED_INTERFACE(), iTokenRateObserver._hex); + assert.equalBN(await tokenRateNotifier.observersLength(), 0); + }) + + .test("addObserver() :: not the owner", async (ctx) => { + const { tokenRateNotifier } = ctx.contracts; + const { stranger } = ctx.accounts; + + await assert.revertsWith( + tokenRateNotifier + .connect(stranger) + .addObserver(ethers.constants.AddressZero), + "Ownable: caller is not the owner" + ); + }) + + .test("addObserver() :: revert on adding zero address observer", async (ctx) => { + const { tokenRateNotifier } = ctx.contracts; + + await assert.revertsWith( + tokenRateNotifier + .connect(ctx.accounts.owner) + .addObserver(ethers.constants.AddressZero), + "ErrorZeroAddressObserver()" + ); + }) + + .test("addObserver() :: revert on adding observer with bad interface", async (ctx) => { + const { tokenRateNotifier } = ctx.contracts; + const { deployer } = ctx.accounts; + + const observer = await new TokenRateNotifier__factory(deployer).deploy(deployer.address); + await assert.revertsWith( + tokenRateNotifier + .connect(ctx.accounts.owner) + .addObserver(observer.address), + "ErrorBadObserverInterface()" + ); + }) + + .test("addObserver() :: revert on adding too many observers", async (ctx) => { + const { tokenRateNotifier, opStackTokenRatePusher } = ctx.contracts; + + assert.equalBN(await tokenRateNotifier.observersLength(), 0); + const maxObservers = await tokenRateNotifier.MAX_OBSERVERS_COUNT(); + for (let i = 0; i < maxObservers.toNumber(); i++) { + await tokenRateNotifier + .connect(ctx.accounts.owner) + .addObserver(opStackTokenRatePusher.address); + } + assert.equalBN(await tokenRateNotifier.observersLength(), maxObservers); + + await assert.revertsWith( + tokenRateNotifier + .connect(ctx.accounts.owner) + .addObserver(opStackTokenRatePusher.address), + "ErrorMaxObserversCountExceeded()" + ); + }) + + .test("addObserver() :: happy path of adding observer", async (ctx) => { + const { tokenRateNotifier, opStackTokenRatePusher } = ctx.contracts; + + assert.equalBN(await tokenRateNotifier.observersLength(), 0); + const tx = await tokenRateNotifier + .connect(ctx.accounts.owner) + .addObserver(opStackTokenRatePusher.address); + assert.equalBN(await tokenRateNotifier.observersLength(), 1); + + await assert.emits(tokenRateNotifier, tx, "ObserverAdded", [opStackTokenRatePusher.address]); + }) + + .test("removeObserver() :: revert on calling by not the owner", async (ctx) => { + const { tokenRateNotifier } = ctx.contracts; + const { stranger } = ctx.accounts; + + await assert.revertsWith( + tokenRateNotifier + .connect(stranger) + .removeObserver(ethers.constants.AddressZero), + "Ownable: caller is not the owner" + ); + }) + + .test("removeObserver() :: revert on removing non-added observer", async (ctx) => { + const { tokenRateNotifier, opStackTokenRatePusher } = ctx.contracts; + + assert.equalBN(await tokenRateNotifier.observersLength(), 0); + + await assert.revertsWith( + tokenRateNotifier + .connect(ctx.accounts.owner) + .removeObserver(opStackTokenRatePusher.address), + "ErrorNoObserverToRemove()" + ); + }) + + .test("removeObserver() :: happy path of removing observer", async (ctx) => { + const { tokenRateNotifier, opStackTokenRatePusher } = ctx.contracts; + + assert.equalBN(await tokenRateNotifier.observersLength(), 0); + + await tokenRateNotifier + .connect(ctx.accounts.owner) + .addObserver(opStackTokenRatePusher.address); + + assert.equalBN(await tokenRateNotifier.observersLength(), 1); + + const tx = await tokenRateNotifier + .connect(ctx.accounts.owner) + .removeObserver(opStackTokenRatePusher.address); + await assert.emits(tokenRateNotifier, tx, "ObserverRemoved", [opStackTokenRatePusher.address]); + + assert.equalBN(await tokenRateNotifier.observersLength(), 0); + }) + + .test("handlePostTokenRebase() :: failed with some error", async (ctx) => { + const { tokenRateNotifier } = ctx.contracts; + const { deployer } = ctx.accounts; + + const observer = await new OpStackTokenRatePusherWithSomeErrorStub__factory(deployer).deploy(); + await tokenRateNotifier + .connect(ctx.accounts.owner) + .addObserver(observer.address); + + const tx = await tokenRateNotifier.handlePostTokenRebase(1, 2, 3, 4, 5, 6, 7); + + await assert.emits(tokenRateNotifier, tx, "PushTokenRateFailed", [observer.address, "0x332e27d2"]); + }) + + .test("handlePostTokenRebase() :: revert when observer has out of gas error", async (ctx) => { + const { tokenRateNotifier } = ctx.contracts; + const { deployer } = ctx.accounts; + + const observer = await new OpStackTokenRatePusherWithOutOfGasErrorStub__factory(deployer).deploy(); + await tokenRateNotifier + .connect(ctx.accounts.owner) + .addObserver(observer.address); + + await assert.revertsWith( + tokenRateNotifier.handlePostTokenRebase(1, 2, 3, 4, 5, 6, 7), + "ErrorTokenRateNotifierRevertedWithNoData()" + ); + }) + + .test("handlePostTokenRebase() :: happy path of handling token rebase", async (ctx) => { + const { + tokenRateNotifier, + l1MessengerStub, + opStackTokenRatePusher, + l1TokenNonRebasableStub + } = ctx.contracts; + const { tokenRateOracle } = ctx.accounts; + const { l2GasLimitForPushingTokenRate } = ctx.constants; + + let tokenRate = await l1TokenNonRebasableStub.stEthPerToken(); + await tokenRateNotifier + .connect(ctx.accounts.owner) + .addObserver(opStackTokenRatePusher.address); + let tx = await tokenRateNotifier.handlePostTokenRebase(1, 2, 3, 4, 5, 6, 7); + + const provider = await ethers.provider; + const blockNumber = await provider.getBlockNumber(); + const blockTimestamp = (await provider.getBlock(blockNumber)).timestamp; + + await assert.emits(l1MessengerStub, tx, "SentMessage", [ + tokenRateOracle.address, + opStackTokenRatePusher.address, + ITokenRateOracle__factory.createInterface().encodeFunctionData( + "updateRate", + [ + tokenRate, + blockTimestamp + ] + ), + 1, + l2GasLimitForPushingTokenRate, + ]); + }) + + .run(); async function ctxFactory() { - const [deployer, bridge, stranger, tokenRateOracle] = await ethers.getSigners(); - const tokenRateNotifier = await new TokenRateNotifier__factory(deployer).deploy(); + const [deployer, owner, stranger, tokenRateOracle] = await ethers.getSigners(); + const tokenRateNotifier = await new TokenRateNotifier__factory(deployer).deploy(owner.address); const l1TokenRebasableStub = await new ERC20BridgedStub__factory(deployer).deploy( - "L1 Token Rebasable", - "L1R" + "L1 Token Rebasable", + "L1R" ); const l1TokenNonRebasableStub = await new ERC20WrapperStub__factory(deployer).deploy( - l1TokenRebasableStub.address, - "L1 Token Non Rebasable", - "L1NR" + l1TokenRebasableStub.address, + "L1 Token Non Rebasable", + "L1NR" ); const l1MessengerStub = await new CrossDomainMessengerStub__factory( - deployer + deployer ).deploy({ value: wei.toBigNumber(wei`1 ether`) }); const l2GasLimitForPushingTokenRate = 123; const opStackTokenRatePusher = await new OpStackTokenRatePusher__factory(deployer).deploy( - l1MessengerStub.address, - l1TokenNonRebasableStub.address, - tokenRateOracle.address, - l2GasLimitForPushingTokenRate + l1MessengerStub.address, + l1TokenNonRebasableStub.address, + tokenRateOracle.address, + l2GasLimitForPushingTokenRate ); return { - accounts: { deployer, bridge, stranger, tokenRateOracle }, - contracts: { tokenRateNotifier, opStackTokenRatePusher, l1MessengerStub, l1TokenNonRebasableStub }, - constants: { l2GasLimitForPushingTokenRate } + accounts: { deployer, owner, stranger, tokenRateOracle }, + contracts: { tokenRateNotifier, opStackTokenRatePusher, l1MessengerStub, l1TokenNonRebasableStub }, + constants: { l2GasLimitForPushingTokenRate } }; } diff --git a/test/optimism/bridging-rebasable-to.e2e.test.ts b/test/optimism/bridging-rebasable-to.e2e.test.ts index ca58277..6dc3d5a 100644 --- a/test/optimism/bridging-rebasable-to.e2e.test.ts +++ b/test/optimism/bridging-rebasable-to.e2e.test.ts @@ -80,7 +80,7 @@ import { }) .step("Withdraw tokens from L2 via withdrawERC20To()", async (ctx) => { - withdrawTokensTxResponse = await ctx.l2ERC20TokenBridge + withdrawTokensTxResponse = await ctx.l2ERC20ExtendedTokensBridge .connect(ctx.l2Tester) .withdrawTo( ctx.l2TokenRebasable.address, @@ -147,7 +147,7 @@ import { l1TokenRebasable: testingSetup.l1TokenRebasable, l2TokenRebasable: testingSetup.l2TokenRebasable, l1LidoTokensBridge: testingSetup.l1LidoTokensBridge, - l2ERC20TokenBridge: testingSetup.l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge: testingSetup.l2ERC20ExtendedTokensBridge, crossChainMessenger: new CrossChainMessenger({ l2ChainId: network.chainId("opt", networkName), l1ChainId: network.chainId("eth", networkName), @@ -157,7 +157,7 @@ import { LidoBridge: { Adapter: LidoBridgeAdapter, l1Bridge: testingSetup.l1LidoTokensBridge.address, - l2Bridge: testingSetup.l2ERC20TokenBridge.address, + l2Bridge: testingSetup.l2ERC20ExtendedTokensBridge.address, }, }, }), diff --git a/test/optimism/bridging-rebasable.e2e.test.ts b/test/optimism/bridging-rebasable.e2e.test.ts index 868f0a6..27aaa65 100644 --- a/test/optimism/bridging-rebasable.e2e.test.ts +++ b/test/optimism/bridging-rebasable.e2e.test.ts @@ -144,7 +144,7 @@ import { LidoBridge: { Adapter: LidoBridgeAdapter, l1Bridge: testingSetup.l1LidoTokensBridge.address, - l2Bridge: testingSetup.l2ERC20TokenBridge.address, + l2Bridge: testingSetup.l2ERC20ExtendedTokensBridge.address, }, }, }), diff --git a/test/optimism/bridging-rebasable.integration.test.ts b/test/optimism/bridging-rebasable.integration.test.ts index 68cbabe..fbe208a 100644 --- a/test/optimism/bridging-rebasable.integration.test.ts +++ b/test/optimism/bridging-rebasable.integration.test.ts @@ -17,13 +17,13 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .step("Activate bridging on L1", async (ctx) => { const { l1LidoTokensBridge } = ctx; - const { l1ERC20TokenBridgeAdmin } = ctx.accounts; + const { l1ERC20ExtendedTokensBridgeAdmin } = ctx.accounts; const isDepositsEnabled = await l1LidoTokensBridge.isDepositsEnabled(); if (!isDepositsEnabled) { await l1LidoTokensBridge - .connect(l1ERC20TokenBridgeAdmin) + .connect(l1ERC20ExtendedTokensBridgeAdmin) .enableDeposits(); } else { console.log("L1 deposits already enabled"); @@ -34,7 +34,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) if (!isWithdrawalsEnabled) { await l1LidoTokensBridge - .connect(l1ERC20TokenBridgeAdmin) + .connect(l1ERC20ExtendedTokensBridgeAdmin) .enableWithdrawals(); } else { console.log("L1 withdrawals already enabled"); @@ -45,32 +45,32 @@ scenario("Optimism :: Bridging integration test", ctxFactory) }) .step("Activate bridging on L2", async (ctx) => { - const { l2ERC20TokenBridge } = ctx; - const { l2ERC20TokenBridgeAdmin } = ctx.accounts; + const { l2ERC20ExtendedTokensBridge } = ctx; + const { l2ERC20ExtendedTokensBridgeAdmin } = ctx.accounts; - const isDepositsEnabled = await l2ERC20TokenBridge.isDepositsEnabled(); + const isDepositsEnabled = await l2ERC20ExtendedTokensBridge.isDepositsEnabled(); if (!isDepositsEnabled) { - await l2ERC20TokenBridge - .connect(l2ERC20TokenBridgeAdmin) + await l2ERC20ExtendedTokensBridge + .connect(l2ERC20ExtendedTokensBridgeAdmin) .enableDeposits(); } else { console.log("L2 deposits already enabled"); } const isWithdrawalsEnabled = - await l2ERC20TokenBridge.isWithdrawalsEnabled(); + await l2ERC20ExtendedTokensBridge.isWithdrawalsEnabled(); if (!isWithdrawalsEnabled) { - await l2ERC20TokenBridge - .connect(l2ERC20TokenBridgeAdmin) + await l2ERC20ExtendedTokensBridge + .connect(l2ERC20ExtendedTokensBridgeAdmin) .enableWithdrawals(); } else { console.log("L2 withdrawals already enabled"); } - assert.isTrue(await l2ERC20TokenBridge.isDepositsEnabled()); - assert.isTrue(await l2ERC20TokenBridge.isWithdrawalsEnabled()); + assert.isTrue(await l2ERC20ExtendedTokensBridge.isDepositsEnabled()); + assert.isTrue(await l2ERC20ExtendedTokensBridge.isWithdrawalsEnabled()); }) .step("Set up Token Rate Oracle by pushing first rate", async (ctx) => { @@ -81,7 +81,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l2TokenRebasable, l1LidoTokensBridge, l2CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, l2Provider } = ctx; @@ -94,10 +94,10 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .relayMessage( 1, l1LidoTokensBridge.address, - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, 0, 300_000, - l2ERC20TokenBridge.interface.encodeFunctionData("finalizeDeposit", [ + l2ERC20ExtendedTokensBridge.interface.encodeFunctionData("finalizeDeposit", [ l1TokenRebasable.address, l2TokenRebasable.address, tokenHolderA.address, @@ -116,7 +116,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2TokenRebasable, l1CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, l1Provider } = ctx; @@ -130,7 +130,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) tokenHolderA.address ); - const l1ERC20TokenBridgeBalanceBefore = await l1TokenRebasable.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1TokenRebasable.balanceOf( l1LidoTokensBridge.address ); @@ -155,7 +155,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) dataToSend, ]); - const l2DepositCalldata = l2ERC20TokenBridge.interface.encodeFunctionData( + const l2DepositCalldata = l2ERC20ExtendedTokensBridge.interface.encodeFunctionData( "finalizeDeposit", [ l1TokenRebasable.address, @@ -170,7 +170,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const messageNonce = await l1CrossDomainMessenger.messageNonce(); await assert.emits(l1CrossDomainMessenger, tx, "SentMessage", [ - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, l1LidoTokensBridge.address, l2DepositCalldata, messageNonce, @@ -179,7 +179,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) assert.equalBN( await l1Token.balanceOf(l1LidoTokensBridge.address), - l1ERC20TokenBridgeBalanceBefore + l1ERC20ExtendedTokensBridgeBalanceBefore ); assert.equalBN( @@ -195,7 +195,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l2TokenRebasable, l1LidoTokensBridge, l2CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, l2Provider } = ctx; @@ -215,10 +215,10 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .relayMessage( 1, l1LidoTokensBridge.address, - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, 0, 300_000, - l2ERC20TokenBridge.interface.encodeFunctionData("finalizeDeposit", [ + l2ERC20ExtendedTokensBridge.interface.encodeFunctionData("finalizeDeposit", [ l1TokenRebasable.address, l2TokenRebasable.address, tokenHolderA.address, @@ -229,7 +229,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) { gasLimit: 5_000_000 } ); - await assert.emits(l2ERC20TokenBridge, tx, "DepositFinalized", [ + await assert.emits(l2ERC20ExtendedTokensBridge, tx, "DepositFinalized", [ l1TokenRebasable.address, l2TokenRebasable.address, tokenHolderA.address, @@ -255,7 +255,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2TokenRebasable, l1CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, l1Provider } = ctx; const { accountA: tokenHolderA } = ctx.accounts; @@ -269,7 +269,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) tokenHolderA.address ); - const l1ERC20TokenBridgeBalanceBefore = await l1TokenRebasable.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1TokenRebasable.balanceOf( l1LidoTokensBridge.address ); @@ -294,7 +294,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) dataToSend, ]); - const l2DepositCalldata = l2ERC20TokenBridge.interface.encodeFunctionData( + const l2DepositCalldata = l2ERC20ExtendedTokensBridge.interface.encodeFunctionData( "finalizeDeposit", [ l1TokenRebasable.address, @@ -309,7 +309,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const messageNonce = await l1CrossDomainMessenger.messageNonce(); await assert.emits(l1CrossDomainMessenger, tx, "SentMessage", [ - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, l1LidoTokensBridge.address, l2DepositCalldata, messageNonce, @@ -318,7 +318,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) assert.equalBN( await l1Token.balanceOf(l1LidoTokensBridge.address), - l1ERC20TokenBridgeBalanceBefore.add(depositAmountNonRebasable) + l1ERC20ExtendedTokensBridgeBalanceBefore.add(depositAmountNonRebasable) ); assert.equalBN( @@ -334,7 +334,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l2TokenRebasable, l1LidoTokensBridge, l2CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, l2Provider } = ctx; const { depositAmountNonRebasable, depositAmountRebasable } = ctx.common; @@ -354,10 +354,10 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .relayMessage( 1, l1LidoTokensBridge.address, - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, 0, 300_000, - l2ERC20TokenBridge.interface.encodeFunctionData("finalizeDeposit", [ + l2ERC20ExtendedTokensBridge.interface.encodeFunctionData("finalizeDeposit", [ l1TokenRebasable.address, l2TokenRebasable.address, tokenHolderA.address, @@ -368,7 +368,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) { gasLimit: 5_000_000 } ); - await assert.emits(l2ERC20TokenBridge, tx, "DepositFinalized", [ + await assert.emits(l2ERC20ExtendedTokensBridge, tx, "DepositFinalized", [ l1TokenRebasable.address, l2TokenRebasable.address, tokenHolderA.address, @@ -393,7 +393,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const { l1TokenRebasable, l2TokenRebasable, - l2ERC20TokenBridge + l2ERC20ExtendedTokensBridge } = ctx; const tokenHolderABalanceBefore = await l2TokenRebasable.balanceOf( @@ -401,7 +401,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) ); const l2TotalSupplyBefore = await l2TokenRebasable.totalSupply(); - const tx = await l2ERC20TokenBridge + const tx = await l2ERC20ExtendedTokensBridge .connect(tokenHolderA.l2Signer) .withdraw( l2TokenRebasable.address, @@ -410,7 +410,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) "0x" ); - await assert.emits(l2ERC20TokenBridge, tx, "WithdrawalInitiated", [ + await assert.emits(l2ERC20ExtendedTokensBridge, tx, "WithdrawalInitiated", [ l1TokenRebasable.address, l2TokenRebasable.address, tokenHolderA.address, @@ -437,7 +437,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2CrossDomainMessenger, l2TokenRebasable, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, } = ctx; const { accountA: tokenHolderA, l1Stranger } = ctx.accounts; const { withdrawalAmountNonRebasable, withdrawalAmountRebasable } = ctx.common; @@ -445,13 +445,13 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const tokenHolderABalanceBefore = await l1TokenRebasable.balanceOf( tokenHolderA.address ); - const l1ERC20TokenBridgeBalanceBefore = await l1Token.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1Token.balanceOf( l1LidoTokensBridge.address ); await l1CrossDomainMessenger .connect(l1Stranger) - .setXDomainMessageSender(l2ERC20TokenBridge.address); + .setXDomainMessageSender(l2ERC20ExtendedTokensBridge.address); const tx = await l1CrossDomainMessenger .connect(l1Stranger) @@ -483,7 +483,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) assert.equalBN( await l1Token.balanceOf(l1LidoTokensBridge.address), - l1ERC20TokenBridgeBalanceBefore.sub(withdrawalAmountNonRebasable) + l1ERC20ExtendedTokensBridgeBalanceBefore.sub(withdrawalAmountNonRebasable) ); assert.equalBN( @@ -501,7 +501,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2TokenRebasable, l1CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, l1Provider } = ctx; const { accountA: tokenHolderA, accountB: tokenHolderB } = ctx.accounts; @@ -518,7 +518,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const tokenHolderABalanceBefore = await l1TokenRebasable.balanceOf( tokenHolderA.address ); - const l1ERC20TokenBridgeBalanceBefore = await l1Token.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1Token.balanceOf( l1LidoTokensBridge.address ); @@ -544,7 +544,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) dataToSend, ]); - const l2DepositCalldata = l2ERC20TokenBridge.interface.encodeFunctionData( + const l2DepositCalldata = l2ERC20ExtendedTokensBridge.interface.encodeFunctionData( "finalizeDeposit", [ l1TokenRebasable.address, @@ -559,7 +559,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const messageNonce = await l1CrossDomainMessenger.messageNonce(); await assert.emits(l1CrossDomainMessenger, tx, "SentMessage", [ - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, l1LidoTokensBridge.address, l2DepositCalldata, messageNonce, @@ -568,7 +568,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) assert.equalBN( await l1Token.balanceOf(l1LidoTokensBridge.address), - l1ERC20TokenBridgeBalanceBefore.add(depositAmountNonRebasable) + l1ERC20ExtendedTokensBridgeBalanceBefore.add(depositAmountNonRebasable) ); assert.equalBN( @@ -584,7 +584,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2TokenRebasable, l2CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, l2Provider } = ctx; @@ -612,10 +612,10 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .relayMessage( 1, l1LidoTokensBridge.address, - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, 0, 300_000, - l2ERC20TokenBridge.interface.encodeFunctionData("finalizeDeposit", [ + l2ERC20ExtendedTokensBridge.interface.encodeFunctionData("finalizeDeposit", [ l1TokenRebasable.address, l2TokenRebasable.address, tokenHolderA.address, @@ -626,7 +626,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) { gasLimit: 5_000_000 } ); - await assert.emits(l2ERC20TokenBridge, tx, "DepositFinalized", [ + await assert.emits(l2ERC20ExtendedTokensBridge, tx, "DepositFinalized", [ l1TokenRebasable.address, l2TokenRebasable.address, tokenHolderA.address, @@ -647,7 +647,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) }) .step("L2 -> L1 withdrawal via withdrawTo()", async (ctx) => { - const { l1TokenRebasable, l2TokenRebasable, l2ERC20TokenBridge } = ctx; + const { l1TokenRebasable, l2TokenRebasable, l2ERC20ExtendedTokensBridge } = ctx; const { accountA: tokenHolderA, accountB: tokenHolderB } = ctx.accounts; const { exchangeRate } = ctx.common; @@ -659,7 +659,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) ); const l2TotalSupplyBefore = await l2TokenRebasable.totalSupply(); - const tx = await l2ERC20TokenBridge + const tx = await l2ERC20ExtendedTokensBridge .connect(tokenHolderB.l2Signer) .withdrawTo( l2TokenRebasable.address, @@ -669,7 +669,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) "0x" ); - await assert.emits(l2ERC20TokenBridge, tx, "WithdrawalInitiated", [ + await assert.emits(l2ERC20ExtendedTokensBridge, tx, "WithdrawalInitiated", [ l1TokenRebasable.address, l2TokenRebasable.address, tokenHolderB.address, @@ -697,7 +697,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2CrossDomainMessenger, l2TokenRebasable, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, } = ctx; const { accountA: tokenHolderA, @@ -712,13 +712,13 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const tokenHolderABalanceBefore = await l1TokenRebasable.balanceOf( tokenHolderA.address ); - const l1ERC20TokenBridgeBalanceBefore = await l1Token.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1Token.balanceOf( l1LidoTokensBridge.address ); await l1CrossDomainMessenger .connect(l1Stranger) - .setXDomainMessageSender(l2ERC20TokenBridge.address); + .setXDomainMessageSender(l2ERC20ExtendedTokensBridge.address); const tx = await l1CrossDomainMessenger .connect(l1Stranger) @@ -750,7 +750,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) assert.equalBN( await l1Token.balanceOf(l1LidoTokensBridge.address), - l1ERC20TokenBridgeBalanceBefore.sub(withdrawalAmountNonRebasable) + l1ERC20ExtendedTokensBridgeBalanceBefore.sub(withdrawalAmountNonRebasable) ); assert.equalBN( @@ -767,8 +767,8 @@ async function ctxFactory() { const { l1Provider, l2Provider, - l1ERC20TokenBridgeAdmin, - l2ERC20TokenBridgeAdmin, + l1ERC20ExtendedTokensBridgeAdmin, + l2ERC20ExtendedTokensBridgeAdmin, ...contracts } = await optimism.testing(networkName).getIntegrationTestSetup(); @@ -794,13 +794,13 @@ async function ctxFactory() { ); await testing.setBalance( - await l1ERC20TokenBridgeAdmin.getAddress(), + await l1ERC20ExtendedTokensBridgeAdmin.getAddress(), wei.toBigNumber(wei`1 ether`), l1Provider ); await testing.setBalance( - await l2ERC20TokenBridgeAdmin.getAddress(), + await l2ERC20ExtendedTokensBridgeAdmin.getAddress(), wei.toBigNumber(wei`1 ether`), l2Provider ); @@ -828,8 +828,8 @@ async function ctxFactory() { accountA, accountB, l1Stranger: testing.accounts.stranger(l1Provider), - l1ERC20TokenBridgeAdmin, - l2ERC20TokenBridgeAdmin, + l1ERC20ExtendedTokensBridgeAdmin, + l2ERC20ExtendedTokensBridgeAdmin, l1CrossDomainMessengerAliased, }, common: { diff --git a/test/optimism/bridging-to.e2e.test.ts b/test/optimism/bridging-to.e2e.test.ts index 5c9788e..13d9833 100644 --- a/test/optimism/bridging-to.e2e.test.ts +++ b/test/optimism/bridging-to.e2e.test.ts @@ -79,7 +79,7 @@ scenario("Optimism :: Bridging via depositTo/withdrawTo E2E test", ctxFactory) }) .step("Withdraw tokens from L2 via withdrawERC20To()", async (ctx) => { - withdrawTokensTxResponse = await ctx.l2ERC20TokenBridge + withdrawTokensTxResponse = await ctx.l2ERC20ExtendedTokensBridge .connect(ctx.l2Tester) .withdrawTo( ctx.l2Token.address, @@ -146,7 +146,7 @@ async function ctxFactory() { l1Token: testingSetup.l1Token, l2Token: testingSetup.l2Token, l1LidoTokensBridge: testingSetup.l1LidoTokensBridge, - l2ERC20TokenBridge: testingSetup.l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge: testingSetup.l2ERC20ExtendedTokensBridge, crossChainMessenger: new CrossChainMessenger({ l2ChainId: network.chainId("opt", networkName), l1ChainId: network.chainId("eth", networkName), @@ -156,7 +156,7 @@ async function ctxFactory() { LidoBridge: { Adapter: DAIBridgeAdapter, l1Bridge: testingSetup.l1LidoTokensBridge.address, - l2Bridge: testingSetup.l2ERC20TokenBridge.address, + l2Bridge: testingSetup.l2ERC20ExtendedTokensBridge.address, }, }, }), diff --git a/test/optimism/bridging.e2e.test.ts b/test/optimism/bridging.e2e.test.ts index ea346bd..c045267 100644 --- a/test/optimism/bridging.e2e.test.ts +++ b/test/optimism/bridging.e2e.test.ts @@ -144,7 +144,7 @@ async function ctxFactory() { LidoBridge: { Adapter: LidoBridgeAdapter, l1Bridge: testingSetup.l1LidoTokensBridge.address, - l2Bridge: testingSetup.l2ERC20TokenBridge.address, + l2Bridge: testingSetup.l2ERC20ExtendedTokensBridge.address, }, }, }), diff --git a/test/optimism/bridging.integration.test.ts b/test/optimism/bridging.integration.test.ts index 57d9e5b..6cc2a50 100644 --- a/test/optimism/bridging.integration.test.ts +++ b/test/optimism/bridging.integration.test.ts @@ -13,13 +13,13 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .step("Activate bridging on L1", async (ctx) => { const { l1LidoTokensBridge } = ctx; - const { l1ERC20TokenBridgeAdmin } = ctx.accounts; + const { l1ERC20ExtendedTokensBridgeAdmin } = ctx.accounts; const isDepositsEnabled = await l1LidoTokensBridge.isDepositsEnabled(); if (!isDepositsEnabled) { await l1LidoTokensBridge - .connect(l1ERC20TokenBridgeAdmin) + .connect(l1ERC20ExtendedTokensBridgeAdmin) .enableDeposits(); } else { console.log("L1 deposits already enabled"); @@ -30,7 +30,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) if (!isWithdrawalsEnabled) { await l1LidoTokensBridge - .connect(l1ERC20TokenBridgeAdmin) + .connect(l1ERC20ExtendedTokensBridgeAdmin) .enableWithdrawals(); } else { console.log("L1 withdrawals already enabled"); @@ -41,32 +41,32 @@ scenario("Optimism :: Bridging integration test", ctxFactory) }) .step("Activate bridging on L2", async (ctx) => { - const { l2ERC20TokenBridge } = ctx; - const { l2ERC20TokenBridgeAdmin } = ctx.accounts; + const { l2ERC20ExtendedTokensBridge } = ctx; + const { l2ERC20ExtendedTokensBridgeAdmin } = ctx.accounts; - const isDepositsEnabled = await l2ERC20TokenBridge.isDepositsEnabled(); + const isDepositsEnabled = await l2ERC20ExtendedTokensBridge.isDepositsEnabled(); if (!isDepositsEnabled) { - await l2ERC20TokenBridge - .connect(l2ERC20TokenBridgeAdmin) + await l2ERC20ExtendedTokensBridge + .connect(l2ERC20ExtendedTokensBridgeAdmin) .enableDeposits(); } else { console.log("L2 deposits already enabled"); } const isWithdrawalsEnabled = - await l2ERC20TokenBridge.isWithdrawalsEnabled(); + await l2ERC20ExtendedTokensBridge.isWithdrawalsEnabled(); if (!isWithdrawalsEnabled) { - await l2ERC20TokenBridge - .connect(l2ERC20TokenBridgeAdmin) + await l2ERC20ExtendedTokensBridge + .connect(l2ERC20ExtendedTokensBridgeAdmin) .enableWithdrawals(); } else { console.log("L2 withdrawals already enabled"); } - assert.isTrue(await l2ERC20TokenBridge.isDepositsEnabled()); - assert.isTrue(await l2ERC20TokenBridge.isWithdrawalsEnabled()); + assert.isTrue(await l2ERC20ExtendedTokensBridge.isDepositsEnabled()); + assert.isTrue(await l2ERC20ExtendedTokensBridge.isWithdrawalsEnabled()); }) .step("L1 -> L2 deposit via depositERC20() method", async (ctx) => { @@ -75,7 +75,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2Token, l1CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, } = ctx; const { accountA: tokenHolderA } = ctx.accounts; const { depositAmount } = ctx.common; @@ -87,7 +87,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const tokenHolderABalanceBefore = await l1Token.balanceOf( tokenHolderA.address ); - const l1ERC20TokenBridgeBalanceBefore = await l1Token.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1Token.balanceOf( l1LidoTokensBridge.address ); @@ -110,7 +110,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) "0x", ]); - const l2DepositCalldata = l2ERC20TokenBridge.interface.encodeFunctionData( + const l2DepositCalldata = l2ERC20ExtendedTokensBridge.interface.encodeFunctionData( "finalizeDeposit", [ l1Token.address, @@ -125,7 +125,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const messageNonce = await l1CrossDomainMessenger.messageNonce(); await assert.emits(l1CrossDomainMessenger, tx, "SentMessage", [ - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, l1LidoTokensBridge.address, l2DepositCalldata, messageNonce, @@ -134,7 +134,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) assert.equalBN( await l1Token.balanceOf(l1LidoTokensBridge.address), - l1ERC20TokenBridgeBalanceBefore.add(depositAmount) + l1ERC20ExtendedTokensBridgeBalanceBefore.add(depositAmount) ); assert.equalBN( @@ -149,7 +149,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l2Token, l1LidoTokensBridge, l2CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, } = ctx; const { depositAmount } = ctx.common; const { accountA: tokenHolderA, l1CrossDomainMessengerAliased } = @@ -165,10 +165,10 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .relayMessage( 1, l1LidoTokensBridge.address, - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, 0, 300_000, - l2ERC20TokenBridge.interface.encodeFunctionData("finalizeDeposit", [ + l2ERC20ExtendedTokensBridge.interface.encodeFunctionData("finalizeDeposit", [ l1Token.address, l2Token.address, tokenHolderA.address, @@ -179,7 +179,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) { gasLimit: 5_000_000 } ); - await assert.emits(l2ERC20TokenBridge, tx, "DepositFinalized", [ + await assert.emits(l2ERC20ExtendedTokensBridge, tx, "DepositFinalized", [ l1Token.address, l2Token.address, tokenHolderA.address, @@ -200,18 +200,18 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .step("L2 -> L1 withdrawal via withdraw()", async (ctx) => { const { accountA: tokenHolderA } = ctx.accounts; const { withdrawalAmount } = ctx.common; - const { l1Token, l2Token, l2ERC20TokenBridge } = ctx; + const { l1Token, l2Token, l2ERC20ExtendedTokensBridge } = ctx; const tokenHolderABalanceBefore = await l2Token.balanceOf( tokenHolderA.address ); const l2TotalSupplyBefore = await l2Token.totalSupply(); - const tx = await l2ERC20TokenBridge + const tx = await l2ERC20ExtendedTokensBridge .connect(tokenHolderA.l2Signer) .withdraw(l2Token.address, withdrawalAmount, 0, "0x"); - await assert.emits(l2ERC20TokenBridge, tx, "WithdrawalInitiated", [ + await assert.emits(l2ERC20ExtendedTokensBridge, tx, "WithdrawalInitiated", [ l1Token.address, l2Token.address, tokenHolderA.address, @@ -236,7 +236,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2CrossDomainMessenger, l2Token, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, } = ctx; const { accountA: tokenHolderA, l1Stranger } = ctx.accounts; const { withdrawalAmount } = ctx.common; @@ -244,13 +244,13 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const tokenHolderABalanceBefore = await l1Token.balanceOf( tokenHolderA.address ); - const l1ERC20TokenBridgeBalanceBefore = await l1Token.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1Token.balanceOf( l1LidoTokensBridge.address ); await l1CrossDomainMessenger .connect(l1Stranger) - .setXDomainMessageSender(l2ERC20TokenBridge.address); + .setXDomainMessageSender(l2ERC20ExtendedTokensBridge.address); const tx = await l1CrossDomainMessenger .connect(l1Stranger) @@ -282,7 +282,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) assert.equalBN( await l1Token.balanceOf(l1LidoTokensBridge.address), - l1ERC20TokenBridgeBalanceBefore.sub(withdrawalAmount) + l1ERC20ExtendedTokensBridgeBalanceBefore.sub(withdrawalAmount) ); assert.equalBN( @@ -296,7 +296,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1Token, l2Token, l1LidoTokensBridge, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, l1CrossDomainMessenger, } = ctx; const { accountA: tokenHolderA, accountB: tokenHolderB } = ctx.accounts; @@ -311,7 +311,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const tokenHolderABalanceBefore = await l1Token.balanceOf( tokenHolderA.address ); - const l1ERC20TokenBridgeBalanceBefore = await l1Token.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1Token.balanceOf( l1LidoTokensBridge.address ); @@ -335,7 +335,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) "0x", ]); - const l2DepositCalldata = l2ERC20TokenBridge.interface.encodeFunctionData( + const l2DepositCalldata = l2ERC20ExtendedTokensBridge.interface.encodeFunctionData( "finalizeDeposit", [ l1Token.address, @@ -350,7 +350,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const messageNonce = await l1CrossDomainMessenger.messageNonce(); await assert.emits(l1CrossDomainMessenger, tx, "SentMessage", [ - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, l1LidoTokensBridge.address, l2DepositCalldata, messageNonce, @@ -359,7 +359,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) assert.equalBN( await l1Token.balanceOf(l1LidoTokensBridge.address), - l1ERC20TokenBridgeBalanceBefore.add(depositAmount) + l1ERC20ExtendedTokensBridgeBalanceBefore.add(depositAmount) ); assert.equalBN( @@ -374,7 +374,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2Token, l2CrossDomainMessenger, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, } = ctx; const { accountA: tokenHolderA, @@ -393,10 +393,10 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .relayMessage( 1, l1LidoTokensBridge.address, - l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge.address, 0, 300_000, - l2ERC20TokenBridge.interface.encodeFunctionData("finalizeDeposit", [ + l2ERC20ExtendedTokensBridge.interface.encodeFunctionData("finalizeDeposit", [ l1Token.address, l2Token.address, tokenHolderA.address, @@ -407,7 +407,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) { gasLimit: 5_000_000 } ); - await assert.emits(l2ERC20TokenBridge, tx, "DepositFinalized", [ + await assert.emits(l2ERC20ExtendedTokensBridge, tx, "DepositFinalized", [ l1Token.address, l2Token.address, tokenHolderA.address, @@ -427,7 +427,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) }) .step("L2 -> L1 withdrawal via withdrawTo()", async (ctx) => { - const { l1Token, l2Token, l2ERC20TokenBridge } = ctx; + const { l1Token, l2Token, l2ERC20ExtendedTokensBridge } = ctx; const { accountA: tokenHolderA, accountB: tokenHolderB } = ctx.accounts; const { withdrawalAmount } = ctx.common; @@ -436,7 +436,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) ); const l2TotalSupplyBefore = await l2Token.totalSupply(); - const tx = await l2ERC20TokenBridge + const tx = await l2ERC20ExtendedTokensBridge .connect(tokenHolderB.l2Signer) .withdrawTo( l2Token.address, @@ -446,7 +446,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) "0x" ); - await assert.emits(l2ERC20TokenBridge, tx, "WithdrawalInitiated", [ + await assert.emits(l2ERC20ExtendedTokensBridge, tx, "WithdrawalInitiated", [ l1Token.address, l2Token.address, tokenHolderB.address, @@ -473,7 +473,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) l1LidoTokensBridge, l2CrossDomainMessenger, l2Token, - l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge, } = ctx; const { accountA: tokenHolderA, @@ -485,13 +485,13 @@ scenario("Optimism :: Bridging integration test", ctxFactory) const tokenHolderABalanceBefore = await l1Token.balanceOf( tokenHolderA.address ); - const l1ERC20TokenBridgeBalanceBefore = await l1Token.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1Token.balanceOf( l1LidoTokensBridge.address ); await l1CrossDomainMessenger .connect(l1Stranger) - .setXDomainMessageSender(l2ERC20TokenBridge.address); + .setXDomainMessageSender(l2ERC20ExtendedTokensBridge.address); const tx = await l1CrossDomainMessenger .connect(l1Stranger) @@ -523,7 +523,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) assert.equalBN( await l1Token.balanceOf(l1LidoTokensBridge.address), - l1ERC20TokenBridgeBalanceBefore.sub(withdrawalAmount) + l1ERC20ExtendedTokensBridgeBalanceBefore.sub(withdrawalAmount) ); assert.equalBN( @@ -540,8 +540,8 @@ async function ctxFactory() { const { l1Provider, l2Provider, - l1ERC20TokenBridgeAdmin, - l2ERC20TokenBridgeAdmin, + l1ERC20ExtendedTokensBridgeAdmin, + l2ERC20ExtendedTokensBridgeAdmin, ...contracts } = await optimism.testing(networkName).getIntegrationTestSetup(); @@ -563,13 +563,13 @@ async function ctxFactory() { ); await testing.setBalance( - await l1ERC20TokenBridgeAdmin.getAddress(), + await l1ERC20ExtendedTokensBridgeAdmin.getAddress(), wei.toBigNumber(wei`1 ether`), l1Provider ); await testing.setBalance( - await l2ERC20TokenBridgeAdmin.getAddress(), + await l2ERC20ExtendedTokensBridgeAdmin.getAddress(), wei.toBigNumber(wei`1 ether`), l2Provider ); @@ -597,8 +597,8 @@ async function ctxFactory() { accountA, accountB, l1Stranger: testing.accounts.stranger(l1Provider), - l1ERC20TokenBridgeAdmin, - l2ERC20TokenBridgeAdmin, + l1ERC20ExtendedTokensBridgeAdmin, + l2ERC20ExtendedTokensBridgeAdmin, l1CrossDomainMessengerAliased, }, common: { diff --git a/test/optimism/deployment.acceptance.test.ts b/test/optimism/deployment.acceptance.test.ts index b5a7a76..ec30d93 100644 --- a/test/optimism/deployment.acceptance.test.ts +++ b/test/optimism/deployment.acceptance.test.ts @@ -44,7 +44,7 @@ scenario("Optimism Bridge :: deployment acceptance test", ctxFactory) .step("L1 bridge :: L2 token bridge", async (ctx) => { assert.equal( await ctx.l1LidoTokensBridge.l2TokenBridge(), - ctx.l2ERC20TokenBridge.address + ctx.l2ERC20ExtendedTokensBridge.address ); }) .step("L1 Bridge :: is deposits enabled", async (ctx) => { @@ -122,55 +122,55 @@ scenario("Optimism Bridge :: deployment acceptance test", ctxFactory) .step("L2 Bridge :: proxy admin", async (ctx) => { assert.equal( - await ctx.l2ERC20TokenBridgeProxy.proxy__getAdmin(), + await ctx.l2ERC20ExtendedTokensBridgeProxy.proxy__getAdmin(), ctx.deployment.l2.proxyAdmin ); }) .step("L2 Bridge :: bridge admin", async (ctx) => { const currentAdmins = await getRoleHolders( - ctx.l2ERC20TokenBridge, + ctx.l2ERC20ExtendedTokensBridge, BridgingManagerRole.DEFAULT_ADMIN_ROLE.hash ); assert.equal(currentAdmins.size, 1); assert.isTrue(currentAdmins.has(ctx.deployment.l2.bridgeAdmin)); await assert.isTrue( - await ctx.l2ERC20TokenBridge.hasRole( + await ctx.l2ERC20ExtendedTokensBridge.hasRole( BridgingManagerRole.DEFAULT_ADMIN_ROLE.hash, ctx.deployment.l2.bridgeAdmin ) ); }) .step("L2 bridge :: L1 token", async (ctx) => { - assert.equal(await ctx.l2ERC20TokenBridge.L1_TOKEN_NON_REBASABLE(), ctx.deployment.token); + assert.equal(await ctx.l2ERC20ExtendedTokensBridge.L1_TOKEN_NON_REBASABLE(), ctx.deployment.token); }) .step("L2 bridge :: L2 token", async (ctx) => { assert.equal( - await ctx.l2ERC20TokenBridge.L2_TOKEN_NON_REBASABLE(), + await ctx.l2ERC20ExtendedTokensBridge.L2_TOKEN_NON_REBASABLE(), ctx.erc20Bridged.address ); }) .step("L2 bridge :: L1 token bridge", async (ctx) => { assert.equal( - await ctx.l2ERC20TokenBridge.l1TokenBridge(), + await ctx.l2ERC20ExtendedTokensBridge.l1TokenBridge(), ctx.l1LidoTokensBridge.address ); }) .step("L2 Bridge :: is deposits enabled", async (ctx) => { assert.equal( - await ctx.l2ERC20TokenBridge.isDepositsEnabled(), + await ctx.l2ERC20ExtendedTokensBridge.isDepositsEnabled(), ctx.deployment.l2.depositsEnabled ); }) .step("L2 Bridge :: is withdrawals enabled", async (ctx) => { assert.equal( - await ctx.l2ERC20TokenBridge.isWithdrawalsEnabled(), + await ctx.l2ERC20ExtendedTokensBridge.isWithdrawalsEnabled(), ctx.deployment.l2.withdrawalsEnabled ); }) .step("L2 Bridge :: deposits enablers", async (ctx) => { const actualDepositsEnablers = await getRoleHolders( - ctx.l2ERC20TokenBridge, + ctx.l2ERC20ExtendedTokensBridge, BridgingManagerRole.DEPOSITS_ENABLER_ROLE.hash ); const expectedDepositsEnablers = ctx.deployment.l2.depositsEnablers || []; @@ -182,7 +182,7 @@ scenario("Optimism Bridge :: deployment acceptance test", ctxFactory) }) .step("L2 Bridge :: deposits disablers", async (ctx) => { const actualDepositsDisablers = await getRoleHolders( - ctx.l2ERC20TokenBridge, + ctx.l2ERC20ExtendedTokensBridge, BridgingManagerRole.DEPOSITS_DISABLER_ROLE.hash ); const expectedDepositsDisablers = ctx.deployment.l2.depositsDisablers || []; @@ -197,7 +197,7 @@ scenario("Optimism Bridge :: deployment acceptance test", ctxFactory) }) .step("L2 Bridge :: withdrawals enablers", async (ctx) => { const actualWithdrawalsEnablers = await getRoleHolders( - ctx.l2ERC20TokenBridge, + ctx.l2ERC20ExtendedTokensBridge, BridgingManagerRole.WITHDRAWALS_ENABLER_ROLE.hash ); const expectedWithdrawalsEnablers = @@ -213,7 +213,7 @@ scenario("Optimism Bridge :: deployment acceptance test", ctxFactory) }) .step("L2 Bridge :: withdrawals disablers", async (ctx) => { const actualWithdrawalsDisablers = await getRoleHolders( - ctx.l2ERC20TokenBridge, + ctx.l2ERC20ExtendedTokensBridge, BridgingManagerRole.WITHDRAWALS_DISABLER_ROLE.hash ); const expectedWithdrawalsDisablers = @@ -251,7 +251,7 @@ scenario("Optimism Bridge :: deployment acceptance test", ctxFactory) .step("L2 token :: bridge", async (ctx) => { assert.equalBN( await ctx.erc20Bridged.bridge(), - ctx.l2ERC20TokenBridge.address + ctx.l2ERC20ExtendedTokensBridge.address ); }) @@ -287,9 +287,9 @@ async function ctxFactory() { testingSetup.l1LidoTokensBridge.address, testingSetup.l1Provider ), - l2ERC20TokenBridge: testingSetup.l2ERC20TokenBridge, - l2ERC20TokenBridgeProxy: OssifiableProxy__factory.connect( - testingSetup.l2ERC20TokenBridge.address, + l2ERC20ExtendedTokensBridge: testingSetup.l2ERC20ExtendedTokensBridge, + l2ERC20ExtendedTokensBridgeProxy: OssifiableProxy__factory.connect( + testingSetup.l2ERC20ExtendedTokensBridge.address, testingSetup.l2Provider ), erc20Bridged: testingSetup.l2Token, diff --git a/test/optimism/deposit-gas-estimation.test.ts b/test/optimism/deposit-gas-estimation.test.ts index ea3ae06..e6d4857 100644 --- a/test/optimism/deposit-gas-estimation.test.ts +++ b/test/optimism/deposit-gas-estimation.test.ts @@ -13,13 +13,13 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .step("Activate bridging on L1", async (ctx) => { const { l1LidoTokensBridge } = ctx; - const { l1ERC20TokenBridgeAdmin } = ctx.accounts; + const { l1ERC20ExtendedTokensBridgeAdmin } = ctx.accounts; const isDepositsEnabled = await l1LidoTokensBridge.isDepositsEnabled(); if (!isDepositsEnabled) { await l1LidoTokensBridge - .connect(l1ERC20TokenBridgeAdmin) + .connect(l1ERC20ExtendedTokensBridgeAdmin) .enableDeposits(); } else { console.log("L1 deposits already enabled"); @@ -30,7 +30,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) if (!isWithdrawalsEnabled) { await l1LidoTokensBridge - .connect(l1ERC20TokenBridgeAdmin) + .connect(l1ERC20ExtendedTokensBridgeAdmin) .enableWithdrawals(); } else { console.log("L1 withdrawals already enabled"); @@ -41,32 +41,32 @@ scenario("Optimism :: Bridging integration test", ctxFactory) }) .step("Activate bridging on L2", async (ctx) => { - const { l2ERC20TokenBridge } = ctx; - const { l2ERC20TokenBridgeAdmin } = ctx.accounts; + const { l2ERC20ExtendedTokensBridge } = ctx; + const { l2ERC20ExtendedTokensBridgeAdmin } = ctx.accounts; - const isDepositsEnabled = await l2ERC20TokenBridge.isDepositsEnabled(); + const isDepositsEnabled = await l2ERC20ExtendedTokensBridge.isDepositsEnabled(); if (!isDepositsEnabled) { - await l2ERC20TokenBridge - .connect(l2ERC20TokenBridgeAdmin) + await l2ERC20ExtendedTokensBridge + .connect(l2ERC20ExtendedTokensBridgeAdmin) .enableDeposits(); } else { console.log("L2 deposits already enabled"); } const isWithdrawalsEnabled = - await l2ERC20TokenBridge.isWithdrawalsEnabled(); + await l2ERC20ExtendedTokensBridge.isWithdrawalsEnabled(); if (!isWithdrawalsEnabled) { - await l2ERC20TokenBridge - .connect(l2ERC20TokenBridgeAdmin) + await l2ERC20ExtendedTokensBridge + .connect(l2ERC20ExtendedTokensBridgeAdmin) .enableWithdrawals(); } else { console.log("L2 withdrawals already enabled"); } - assert.isTrue(await l2ERC20TokenBridge.isDepositsEnabled()); - assert.isTrue(await l2ERC20TokenBridge.isWithdrawalsEnabled()); + assert.isTrue(await l2ERC20ExtendedTokensBridge.isDepositsEnabled()); + assert.isTrue(await l2ERC20ExtendedTokensBridge.isWithdrawalsEnabled()); }) .step("L1 -> L2 deposit zero tokens via depositERC20() method", async (ctx) => { @@ -83,13 +83,18 @@ scenario("Optimism :: Bridging integration test", ctxFactory) await l1TokenRebasable .connect(tokenHolderA.l1Signer) - .approve(l1LidoTokensBridge.address, 0); + .approve(l1LidoTokensBridge.address, 10); - const tokenHolderABalanceBefore = await l1TokenRebasable.balanceOf( + await l1Token + .connect(tokenHolderA.l1Signer) + .approve(l1LidoTokensBridge.address, 10); + + const tokenHolderABalanceBefore = await l1Token.balanceOf( tokenHolderA.address ); + console.log("tokenHolderABalanceBefore=",tokenHolderABalanceBefore); - const l1ERC20TokenBridgeBalanceBefore = await l1TokenRebasable.balanceOf( + const l1ERC20ExtendedTokensBridgeBalanceBefore = await l1TokenRebasable.balanceOf( l1LidoTokensBridge.address ); @@ -98,7 +103,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .depositERC20( l1Token.address, l2Token.address, - 0, + 10, 200_000, "0x" ); @@ -111,7 +116,7 @@ scenario("Optimism :: Bridging integration test", ctxFactory) .depositERC20( l1TokenRebasable.address, l2TokenRebasable.address, - 0, + 10, 200_000, "0x" ); @@ -134,8 +139,8 @@ async function ctxFactory() { const { l1Provider, l2Provider, - l1ERC20TokenBridgeAdmin, - l2ERC20TokenBridgeAdmin, + l1ERC20ExtendedTokensBridgeAdmin, + l2ERC20ExtendedTokensBridgeAdmin, ...contracts } = await optimism.testing(networkName).getIntegrationTestSetup(); @@ -155,17 +160,21 @@ async function ctxFactory() { ); await testing.setBalance( - await l1ERC20TokenBridgeAdmin.getAddress(), + await l1ERC20ExtendedTokensBridgeAdmin.getAddress(), wei.toBigNumber(wei`1 ether`), l1Provider ); await testing.setBalance( - await l2ERC20TokenBridgeAdmin.getAddress(), + await l2ERC20ExtendedTokensBridgeAdmin.getAddress(), wei.toBigNumber(wei`1 ether`), l2Provider ); + await contracts.l1Token + .connect(contracts.l1TokensHolder) + .transfer(accountA.l1Signer.address, depositAmount); + await contracts.l1TokenRebasable .connect(contracts.l1TokensHolder) .transfer(accountA.l1Signer.address, wei.toBigNumber(depositAmount).mul(2)); @@ -192,8 +201,8 @@ async function ctxFactory() { accountA, accountB, l1Stranger: testing.accounts.stranger(l1Provider), - l1ERC20TokenBridgeAdmin, - l2ERC20TokenBridgeAdmin, + l1ERC20ExtendedTokensBridgeAdmin, + l2ERC20ExtendedTokensBridgeAdmin, l1CrossDomainMessengerAliased, }, common: { diff --git a/test/optimism/managing-deposits.e2e.test.ts b/test/optimism/managing-deposits.e2e.test.ts index 1566d55..36712d5 100644 --- a/test/optimism/managing-deposits.e2e.test.ts +++ b/test/optimism/managing-deposits.e2e.test.ts @@ -2,7 +2,7 @@ import { assert } from "chai"; import { TransactionResponse } from "@ethersproject/providers"; import { - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, GovBridgeExecutor__factory, } from "../../typechain"; import { @@ -33,27 +33,27 @@ const scenarioTest = scenario( assert.gte(await l1LDOHolder.getBalance(), gasAmount); }) - .step("Checking deposits status", async ({ l2ERC20TokenBridge }) => { - l2DepositsInitialState = await l2ERC20TokenBridge.isDepositsEnabled(); + .step("Checking deposits status", async ({ l2ERC20ExtendedTokensBridge }) => { + l2DepositsInitialState = await l2ERC20ExtendedTokensBridge.isDepositsEnabled(); }) .step(`Starting DAO vote`, async (ctx) => { const grantRoleCalldata = - ctx.l2ERC20TokenBridge.interface.encodeFunctionData("grantRole", [ + ctx.l2ERC20ExtendedTokensBridge.interface.encodeFunctionData("grantRole", [ l2DepositsInitialState ? DEPOSIT_DISABLER_ROLE : DEPOSIT_ENABLER_ROLE, ctx.govBridgeExecutor.address, ]); const grantRoleData = "0x" + grantRoleCalldata.substring(10); const actionCalldata = l2DepositsInitialState - ? ctx.l2ERC20TokenBridge.interface.encodeFunctionData("disableDeposits") - : ctx.l2ERC20TokenBridge.interface.encodeFunctionData("enableDeposits"); + ? ctx.l2ERC20ExtendedTokensBridge.interface.encodeFunctionData("disableDeposits") + : ctx.l2ERC20ExtendedTokensBridge.interface.encodeFunctionData("enableDeposits"); const actionData = "0x" + actionCalldata.substring(10); const executorCalldata = await ctx.govBridgeExecutor.interface.encodeFunctionData("queue", [ - [ctx.l2ERC20TokenBridge.address, ctx.l2ERC20TokenBridge.address], + [ctx.l2ERC20ExtendedTokensBridge.address, ctx.l2ERC20ExtendedTokensBridge.address], [0, 0], [ "grantRole(bytes32,address)", @@ -124,9 +124,9 @@ const scenarioTest = scenario( await tx.wait(); }) - .step("Checking deposits state", async ({ l2ERC20TokenBridge }) => { + .step("Checking deposits state", async ({ l2ERC20ExtendedTokensBridge }) => { assert.equal( - await l2ERC20TokenBridge.isDepositsEnabled(), + await l2ERC20ExtendedTokensBridge.isDepositsEnabled(), !l2DepositsInitialState ); }); @@ -158,8 +158,8 @@ async function ctxFactory() { l1Tester, l2Tester, l1LDOHolder, - l2ERC20TokenBridge: L2ERC20TokenBridge__factory.connect( - E2E_TEST_CONTRACTS.l2.l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge: L2ERC20ExtendedTokensBridge__factory.connect( + E2E_TEST_CONTRACTS.l2.l2ERC20ExtendedTokensBridge, l2Tester ), govBridgeExecutor: GovBridgeExecutor__factory.connect( diff --git a/test/optimism/managing-executor.e2e.test.ts b/test/optimism/managing-executor.e2e.test.ts index 340a050..f48112e 100644 --- a/test/optimism/managing-executor.e2e.test.ts +++ b/test/optimism/managing-executor.e2e.test.ts @@ -2,7 +2,7 @@ import { assert } from "chai"; import { TransactionResponse } from "@ethersproject/providers"; import { - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, GovBridgeExecutor__factory, } from "../../typechain"; import { @@ -134,8 +134,8 @@ async function ctxFactory() { gasAmount: wei`0.1 ether`, l2Tester, l1LDOHolder, - l2ERC20TokenBridge: L2ERC20TokenBridge__factory.connect( - E2E_TEST_CONTRACTS.l2.l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge: L2ERC20ExtendedTokensBridge__factory.connect( + E2E_TEST_CONTRACTS.l2.l2ERC20ExtendedTokensBridge, l2Tester ), govBridgeExecutor: GovBridgeExecutor__factory.connect( diff --git a/test/optimism/managing-proxy.e2e.test.ts b/test/optimism/managing-proxy.e2e.test.ts index 632de88..20ff14a 100644 --- a/test/optimism/managing-proxy.e2e.test.ts +++ b/test/optimism/managing-proxy.e2e.test.ts @@ -5,7 +5,7 @@ import { ERC20Bridged__factory, GovBridgeExecutor__factory, OssifiableProxy__factory, - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, } from "../../typechain"; import { E2E_TEST_CONTRACTS_OPTIMISM as E2E_TEST_CONTRACTS } from "../../utils/testing/e2e"; import env from "../../utils/env"; @@ -32,7 +32,7 @@ scenario( .step("Proxy upgrade: send crosschain message", async (ctx) => { const implBefore = await await ctx.proxyToOssify.proxy__getImplementation(); - assert.equal(implBefore, ctx.l2ERC20TokenBridge.address); + assert.equal(implBefore, ctx.l2ERC20ExtendedTokensBridge.address); const executorCalldata = await ctx.govBridgeExecutor.interface.encodeFunctionData("queue", [ [ctx.proxyToOssify.address], @@ -204,8 +204,8 @@ async function ctxFactory() { E2E_TEST_CONTRACTS.l2.l2Token, l2Tester ), - l2ERC20TokenBridge: L2ERC20TokenBridge__factory.connect( - E2E_TEST_CONTRACTS.l2.l2ERC20TokenBridge, + l2ERC20ExtendedTokensBridge: L2ERC20ExtendedTokensBridge__factory.connect( + E2E_TEST_CONTRACTS.l2.l2ERC20ExtendedTokensBridge, l2Tester ), govBridgeExecutor: GovBridgeExecutor__factory.connect( @@ -213,7 +213,7 @@ async function ctxFactory() { l2Tester ), proxyToOssify: await new OssifiableProxy__factory(l2Tester).deploy( - E2E_TEST_CONTRACTS.l2.l2ERC20TokenBridge, + E2E_TEST_CONTRACTS.l2.l2ERC20ExtendedTokensBridge, E2E_TEST_CONTRACTS.l2.govBridgeExecutor, "0x" ), diff --git a/test/optimism/pushingTokenRate.integration.test.ts b/test/optimism/pushingTokenRate.integration.test.ts index 36f93e8..f5d9606 100644 --- a/test/optimism/pushingTokenRate.integration.test.ts +++ b/test/optimism/pushingTokenRate.integration.test.ts @@ -143,12 +143,15 @@ async function ctxFactory() { networkName ).oracleDeployScript( l1Token.address, + 1000, + 86400, { deployer: l1Deployer, admins: { proxy: l1Deployer.address, bridge: l1Deployer.address }, + contractsShift: 0 }, { deployer: l2Deployer, @@ -156,6 +159,7 @@ async function ctxFactory() { proxy: govBridgeExecutor.address, bridge: govBridgeExecutor.address, }, + contractsShift: 0 } ); diff --git a/utils/arbitrum/testing.ts b/utils/arbitrum/testing.ts index e34dce4..081628a 100644 --- a/utils/arbitrum/testing.ts +++ b/utils/arbitrum/testing.ts @@ -206,15 +206,15 @@ async function deployTestGateway( await ethDeployScript.run(); await arbDeployScript.run(); - const l1ERC20TokenBridgeProxyDeployStepIndex = 1; + const l1ERC20ExtendedTokensBridgeProxyDeployStepIndex = 1; const l1BridgingManagement = new BridgingManagement( - ethDeployScript.getContractAddress(l1ERC20TokenBridgeProxyDeployStepIndex), + ethDeployScript.getContractAddress(l1ERC20ExtendedTokensBridgeProxyDeployStepIndex), ethDeployer ); - const l2ERC20TokenBridgeProxyDeployStepIndex = 3; + const l2ERC20ExtendedTokensBridgeProxyDeployStepIndex = 3; const l2BridgingManagement = new BridgingManagement( - arbDeployScript.getContractAddress(l2ERC20TokenBridgeProxyDeployStepIndex), + arbDeployScript.getContractAddress(l2ERC20ExtendedTokensBridgeProxyDeployStepIndex), arbDeployer ); diff --git a/utils/optimism/deploymentAllFromScratch.ts b/utils/optimism/deploymentAllFromScratch.ts index 6b95f1b..8d59c62 100644 --- a/utils/optimism/deploymentAllFromScratch.ts +++ b/utils/optimism/deploymentAllFromScratch.ts @@ -9,7 +9,7 @@ import { ERC20Rebasable__factory, IERC20Metadata__factory, L1LidoTokensBridge__factory, - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, OssifiableProxy__factory, TokenRateOracle__factory, TokenRateNotifier__factory, @@ -163,6 +163,7 @@ export default function deploymentAll( .addStep({ factory: TokenRateNotifier__factory, args: [ + l1Params.deployer.address, options?.overrides, ], afterDeploy: (c) => @@ -265,7 +266,7 @@ export default function deploymentAll( assert.equal(c.address, expectedL2TokenRebasableProxyAddress), }) .addStep({ - factory: L2ERC20TokenBridge__factory, + factory: L2ERC20ExtendedTokensBridge__factory, args: [ optAddresses.L2CrossDomainMessenger, expectedL1TokenBridgeProxyAddress, @@ -283,7 +284,7 @@ export default function deploymentAll( args: [ expectedL2TokenBridgeImplAddress, l2Params.admins.proxy, - L2ERC20TokenBridge__factory.createInterface().encodeFunctionData( + L2ERC20ExtendedTokensBridge__factory.createInterface().encodeFunctionData( "initialize", [l2Params.admins.bridge] ), diff --git a/utils/optimism/deploymentBridgesAndRebasableToken.ts b/utils/optimism/deploymentBridgesAndRebasableToken.ts index 1035b7a..1241ab2 100644 --- a/utils/optimism/deploymentBridgesAndRebasableToken.ts +++ b/utils/optimism/deploymentBridgesAndRebasableToken.ts @@ -9,7 +9,7 @@ import { ERC20Rebasable__factory, IERC20Metadata__factory, L1LidoTokensBridge__factory, - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, OssifiableProxy__factory, } from "../../typechain"; @@ -222,7 +222,7 @@ export default function deployment( assert.equal(c.address, expectedL2TokenRebasableProxyAddress), }) .addStep({ - factory: L2ERC20TokenBridge__factory, + factory: L2ERC20ExtendedTokensBridge__factory, args: [ optAddresses.L2CrossDomainMessenger, expectedL1TokenBridgeProxyAddress, @@ -240,7 +240,7 @@ export default function deployment( args: [ expectedL2TokenBridgeImplAddress, l2Params.admins.proxy, - L2ERC20TokenBridge__factory.createInterface().encodeFunctionData( + L2ERC20ExtendedTokensBridge__factory.createInterface().encodeFunctionData( "initialize", [l2Params.admins.bridge] ), diff --git a/utils/optimism/deploymentNewImplementations.ts b/utils/optimism/deploymentNewImplementations.ts index 706dbf4..6039802 100644 --- a/utils/optimism/deploymentNewImplementations.ts +++ b/utils/optimism/deploymentNewImplementations.ts @@ -9,7 +9,7 @@ import { ERC20Rebasable__factory, IERC20Metadata__factory, L1LidoTokensBridge__factory, - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, OssifiableProxy__factory, TokenRateOracle__factory } from "../../typechain"; @@ -197,7 +197,7 @@ export default function deploymentNewImplementations( assert.equal(c.address, expectedL2TokenRebasableProxyAddress), }) .addStep({ - factory: L2ERC20TokenBridge__factory, + factory: L2ERC20ExtendedTokensBridge__factory, args: [ optAddresses.L2CrossDomainMessenger, l1Params.tokenBridgeProxyAddress, diff --git a/utils/optimism/deploymentOracle.ts b/utils/optimism/deploymentOracle.ts index 002a923..2d43f6b 100644 --- a/utils/optimism/deploymentOracle.ts +++ b/utils/optimism/deploymentOracle.ts @@ -78,6 +78,7 @@ export default function deploymentOracle( .addStep({ factory: TokenRateNotifier__factory, args: [ + l1Params.deployer.address, options?.overrides, ], afterDeploy: (c) => diff --git a/utils/optimism/testing.ts b/utils/optimism/testing.ts index e7848ef..97de55c 100644 --- a/utils/optimism/testing.ts +++ b/utils/optimism/testing.ts @@ -6,13 +6,13 @@ import { ERC20Bridged, IERC20__factory, L1LidoTokensBridge, - L2ERC20TokenBridge, + L2ERC20ExtendedTokensBridge, ERC20Bridged__factory, ERC20BridgedStub__factory, ERC20WrapperStub__factory, TokenRateOracle__factory, L1LidoTokensBridge__factory, - L2ERC20TokenBridge__factory, + L2ERC20ExtendedTokensBridge__factory, CrossDomainMessengerStub__factory, ERC20Rebasable__factory, } from "../../typechain"; @@ -58,11 +58,11 @@ export default function testing(networkName: NetworkName) { ? await loadDeployedBridges(ethProvider, optProvider) : await deployTestBridge(networkName, ethProvider, optProvider); - const [l1ERC20TokenBridgeAdminAddress] = + const [l1ERC20ExtendedTokensAdminAddress] = await BridgingManagement.getAdmins(bridgeContracts.l1LidoTokensBridge); - const [l2ERC20TokenBridgeAdminAddress] = - await BridgingManagement.getAdmins(bridgeContracts.l2ERC20TokenBridge); + const [l2ERC20ExtendedTokensBridgeAdminAddress] = + await BridgingManagement.getAdmins(bridgeContracts.l2ERC20ExtendedTokensBridge); const l1TokensHolder = hasDeployedContracts ? await testingUtils.impersonate( @@ -82,13 +82,13 @@ export default function testing(networkName: NetworkName) { // if the L1 bridge admin is a contract, remove it's code to // make it behave as EOA await ethProvider.send("hardhat_setCode", [ - l1ERC20TokenBridgeAdminAddress, + l1ERC20ExtendedTokensAdminAddress, "0x", ]); // same for the L2 bridge admin await optProvider.send("hardhat_setCode", [ - l2ERC20TokenBridgeAdminAddress, + l2ERC20ExtendedTokensBridgeAdminAddress, "0x", ]); @@ -101,12 +101,12 @@ export default function testing(networkName: NetworkName) { ...bridgeContracts, l1CrossDomainMessenger: optContracts.L1CrossDomainMessengerStub, l2CrossDomainMessenger: optContracts.L2CrossDomainMessenger, - l1ERC20TokenBridgeAdmin: await testingUtils.impersonate( - l1ERC20TokenBridgeAdminAddress, + l1ERC20ExtendedTokensBridgeAdmin: await testingUtils.impersonate( + l1ERC20ExtendedTokensAdminAddress, ethProvider ), - l2ERC20TokenBridgeAdmin: await testingUtils.impersonate( - l2ERC20TokenBridgeAdminAddress, + l2ERC20ExtendedTokensBridgeAdmin: await testingUtils.impersonate( + l2ERC20ExtendedTokensBridgeAdminAddress, optProvider ) }; @@ -170,7 +170,7 @@ async function loadDeployedBridges( l2Token: testingUtils.env.OPT_L2_TOKEN(), l2TokenRebasable: testingUtils.env.OPT_L2_REBASABLE_TOKEN(), l1LidoTokensBridge: testingUtils.env.OPT_L1_ERC20_TOKEN_BRIDGE(), - l2ERC20TokenBridge: testingUtils.env.OPT_L2_ERC20_TOKEN_BRIDGE(), + l2ERC20ExtendedTokensBridge: testingUtils.env.OPT_L2_ERC20_TOKEN_BRIDGE(), }, l1SignerOrProvider, l2SignerOrProvider @@ -248,7 +248,7 @@ async function deployTestBridge( l2Token: optDeployScript.tokenProxyAddress, l2TokenRebasable: optDeployScript.tokenRebasableProxyAddress, l1LidoTokensBridge: ethDeployScript.bridgeProxyAddress, - l2ERC20TokenBridge: optDeployScript.tokenBridgeProxyAddress + l2ERC20ExtendedTokensBridge: optDeployScript.tokenBridgeProxyAddress }, ethProvider, optProvider @@ -262,7 +262,7 @@ function connectBridgeContracts( l2Token: string; l2TokenRebasable: string; l1LidoTokensBridge: string; - l2ERC20TokenBridge: string; + l2ERC20ExtendedTokensBridge: string; }, ethSignerOrProvider: SignerOrProvider, optSignerOrProvider: SignerOrProvider @@ -272,8 +272,8 @@ function connectBridgeContracts( addresses.l1LidoTokensBridge, ethSignerOrProvider ); - const l2ERC20TokenBridge = L2ERC20TokenBridge__factory.connect( - addresses.l2ERC20TokenBridge, + const l2ERC20ExtendedTokensBridge = L2ERC20ExtendedTokensBridge__factory.connect( + addresses.l2ERC20ExtendedTokensBridge, optSignerOrProvider ); const l2Token = ERC20Bridged__factory.connect( @@ -293,7 +293,7 @@ function connectBridgeContracts( l2Token, l2TokenRebasable, l1LidoTokensBridge, - l2ERC20TokenBridge + l2ERC20ExtendedTokensBridge }; } @@ -303,7 +303,7 @@ async function printLoadedTestConfig( l1Token: IERC20; l2Token: ERC20Bridged; l1LidoTokensBridge: L1LidoTokensBridge; - l2ERC20TokenBridge: L2ERC20TokenBridge; + l2ERC20ExtendedTokensBridge: L2ERC20ExtendedTokensBridge; }, l1TokensHolder?: Signer ) { @@ -326,7 +326,7 @@ async function printLoadedTestConfig( ` · L1 ERC20 Token Bridge: ${bridgeContracts.l1LidoTokensBridge.address}` ); console.log( - ` · L2 ERC20 Token Bridge: ${bridgeContracts.l2ERC20TokenBridge.address}` + ` · L2 ERC20 Token Bridge: ${bridgeContracts.l2ERC20ExtendedTokensBridge.address}` ); console.log(); } diff --git a/utils/testing/e2e.ts b/utils/testing/e2e.ts index b089a24..203633e 100644 --- a/utils/testing/e2e.ts +++ b/utils/testing/e2e.ts @@ -8,7 +8,7 @@ export const E2E_TEST_CONTRACTS_OPTIMISM = { l1: { l1Token: "0xB82381A3fBD3FaFA77B3a7bE693342618240067b", l1LDOToken: "0xd06dF83b8ad6D89C86a187fba4Eae918d497BdCB", - l1ERC20TokenBridge: "0x4Abf633d9c0F4aEebB4C2E3213c7aa1b8505D332", + l1ERC20ExtendedTokensBridge: "0x4Abf633d9c0F4aEebB4C2E3213c7aa1b8505D332", aragonVoting: "0x39A0EbdEE54cB319f4F42141daaBDb6ba25D341A", tokenManager: "0xC73cd4B2A7c1CBC5BF046eB4A7019365558ABF66", agent: "0x32A0E5828B62AAb932362a4816ae03b860b65e83", @@ -16,7 +16,7 @@ export const E2E_TEST_CONTRACTS_OPTIMISM = { }, l2: { l2Token: "0x24B47cd3A74f1799b32B2de11073764Cb1bb318B", - l2ERC20TokenBridge: "0xdBA2760246f315203F8B716b3a7590F0FFdc704a", + l2ERC20ExtendedTokensBridge: "0xdBA2760246f315203F8B716b3a7590F0FFdc704a", govBridgeExecutor: "0xf695357C66bA514150Da95b189acb37b46DDe602", }, };