mirror of
https://github.com/vacp2p/linea-monorepo.git
synced 2026-01-06 22:23:55 -05:00
[Feat] Precomputed/Counterfactual address for TokenBridge Remote Sender (#678)
* remove reinit function in tokenbridge * passing tests with removal of setRemoteSender * remove operational task and dead role reference * added tokenbridgev1_1 artifact to e2e tests * adjustments * fix nonce increment
This commit is contained in:
@@ -61,8 +61,6 @@ To deploy the contracts, you will need to run the Bridged Token, Token Bridge, a
|
||||
You can refer to the following links that describe the usage of these scripts. <br />
|
||||
- [Bridged Token Deployment Script](./deployment.md#bridgedtoken) <br />
|
||||
- [Token Bridge Deployment Script](./deployment.md#tokenbridge) <br />
|
||||
- [Operational Script](./operational.md#setRemoteTokenBridge)
|
||||
|
||||
|
||||
All addresses created will be stored in the deployments folder as a separate file. `./contracts/deployment/<network_name>`
|
||||
|
||||
|
||||
@@ -225,46 +225,3 @@ npx hardhat setVerifierAddress \
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
### setRemoteTokenBridge
|
||||
|
||||
<br />
|
||||
Parameters that should be filled either in .env or passed as CLI arguments:
|
||||
|
||||
| Parameter name | Required | Input Value | Description |
|
||||
| ------------------ | -------- | ---------- | ----------- |
|
||||
| \**PRIVATE_KEY* | true | key | Network-specific private key used when deploying the contract |
|
||||
| INFURA_API_KEY | true | key | Infura API Key |
|
||||
| REMOTE_TOKEN_BRIDGE_ADDRESS | true | address | Token Bridge address deployed on the `--remote-network`. It must be provided as CLI argument using the `--remote-token-bridge-address` flag. If not found, the script will also check .env. variable `TOKEN_BRIDGE_ADDRESS`. If the .env variable doesn't exist, it will also check the `deployments/<remote-network>` folder and try to use that address. Otherwise it will throw an error. |
|
||||
| TOKEN_BRIDGE_ADDRESS | true | address | Token Bridge address deployed on current network. It must be provided as CLI argument using the `--token-bridge-address` flag. If not found, the script will also check .env. variable `TOKEN_BRIDGE_ADDRESS`. If the .env variable doesn't exist, it will also check the `deployments/<network_name>` folder and try to use that address. Otherwise it will throw an error. |
|
||||
| --remote-network | true | string | Network name. It must be provided as CLI argument using the `--safe-address` flag otherwise the script will throw an error. |
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
It should be noted that the `--remote-network` and `--network` fields should point to complementary networks.
|
||||
e.g. `--remote-network linea_sepolia --network sepolia` or vice-versa.
|
||||
<br />
|
||||
|
||||
Base command:
|
||||
|
||||
```shell
|
||||
npx hardhat setRemoteTokenBridge --remote-network sepolia --network linea_sepolia
|
||||
```
|
||||
|
||||
Base command with cli arguments:
|
||||
|
||||
```shell
|
||||
SEPOLIA_PRIVATE_KEY=<key> \
|
||||
INFURA_API_KEY=<key> \
|
||||
npx hardhat setRemoteTokenBridge \
|
||||
--remote-token-bridge-address <address> \
|
||||
--token-bridge-address <address> \
|
||||
--remote-network sepolia \
|
||||
--network linea_sepolia
|
||||
```
|
||||
|
||||
(make sure to replace `<key>` with actual values)
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
@@ -13,7 +13,6 @@ import "./scripts/operational/grantContractRolesTask";
|
||||
import "./scripts/operational/renounceContractRolesTask";
|
||||
import "./scripts/operational/setRateLimitTask";
|
||||
import "./scripts/operational/setVerifierAddressTask";
|
||||
import "./scripts/operational/setRemoteTokenBridgeTask";
|
||||
import "./scripts/operational/setMessageServiceOnTokenBridgeTask";
|
||||
|
||||
import "solidity-docgen";
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
contractName as TokenBridgeContractName,
|
||||
abi as TokenBridgeAbi,
|
||||
bytecode as TokenBridgeBytecode,
|
||||
} from "./dynamic-artifacts/TokenBridgeV1.json";
|
||||
} from "./dynamic-artifacts/TokenBridgeV1_1.json";
|
||||
import {
|
||||
contractName as UpgradeableBeaconContractName,
|
||||
abi as UpgradeableBeaconAbi,
|
||||
@@ -58,18 +58,29 @@ async function main() {
|
||||
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
|
||||
|
||||
let walletNonce;
|
||||
let remoteDeployerNonce;
|
||||
|
||||
if (process.env.TOKEN_BRIDGE_L1 === "true") {
|
||||
if (!process.env.L1_NONCE) {
|
||||
walletNonce = await wallet.getNonce();
|
||||
} else {
|
||||
walletNonce = parseInt(process.env.L1_NONCE) + ORDERED_NONCE_POST_LINEAROLLUP;
|
||||
}
|
||||
walletNonce = await getL1DeployerNonce();
|
||||
remoteDeployerNonce = await getL2DeployerNonce();
|
||||
} else {
|
||||
if (!process.env.L2_NONCE) {
|
||||
walletNonce = await wallet.getNonce();
|
||||
walletNonce = await getL2DeployerNonce();
|
||||
remoteDeployerNonce = await getL1DeployerNonce();
|
||||
}
|
||||
|
||||
async function getL1DeployerNonce(): Promise<number> {
|
||||
if (!process.env.L1_NONCE) {
|
||||
return await wallet.getNonce();
|
||||
} else {
|
||||
walletNonce = parseInt(process.env.L2_NONCE) + ORDERED_NONCE_POST_L2MESSAGESERVICE;
|
||||
return parseInt(process.env.L1_NONCE) + ORDERED_NONCE_POST_LINEAROLLUP;
|
||||
}
|
||||
}
|
||||
|
||||
async function getL2DeployerNonce(): Promise<number> {
|
||||
if (!process.env.L2_NONCE) {
|
||||
return await wallet.getNonce();
|
||||
} else {
|
||||
return parseInt(process.env.L2_NONCE) + ORDERED_NONCE_POST_L2MESSAGESERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,10 +120,14 @@ async function main() {
|
||||
let reservedAddresses = process.env.L2_RESERVED_TOKEN_ADDRESSES
|
||||
? process.env.L2_RESERVED_TOKEN_ADDRESSES.split(",")
|
||||
: [];
|
||||
const remoteSender = ethers.getCreateAddress({
|
||||
from: process.env.REMOTE_DEPLOYER_ADDRESS || "",
|
||||
nonce: remoteDeployerNonce + 4,
|
||||
});
|
||||
|
||||
if (process.env.TOKEN_BRIDGE_L1 === "true") {
|
||||
console.log(
|
||||
`TOKEN_BRIDGE_L1=${process.env.TOKEN_BRIDGE_L1}. Deploying TokenBridge on L1, using L1_RESERVED_TOKEN_ADDRESSES environment variable`,
|
||||
`TOKEN_BRIDGE_L1=${process.env.TOKEN_BRIDGE_L1}. Deploying TokenBridge on L1, using L1_RESERVED_TOKEN_ADDRESSES environment variable and remoteSender=${remoteSender}`,
|
||||
);
|
||||
deployingChainMessageService = lineaRollupAddress;
|
||||
reservedAddresses = process.env.L1_RESERVED_TOKEN_ADDRESSES
|
||||
@@ -120,7 +135,7 @@ async function main() {
|
||||
: [];
|
||||
} else {
|
||||
console.log(
|
||||
`TOKEN_BRIDGE_L1=${process.env.TOKEN_BRIDGE_L1}. Deploying TokenBridge on L2, using L2_RESERVED_TOKEN_ADDRESSES environment variable`,
|
||||
`TOKEN_BRIDGE_L1=${process.env.TOKEN_BRIDGE_L1}. Deploying TokenBridge on L2, using L2_RESERVED_TOKEN_ADDRESSES environment variable and remoteSender=${remoteSender}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -131,6 +146,7 @@ async function main() {
|
||||
tokenBeacon: beaconProxyAddress,
|
||||
sourceChainId: chainId,
|
||||
targetChainId: remoteChainId,
|
||||
remoteSender: remoteSender,
|
||||
reservedTokens: reservedAddresses,
|
||||
roleAddresses,
|
||||
pauseTypeRoles,
|
||||
File diff suppressed because one or more lines are too long
@@ -1,61 +0,0 @@
|
||||
// import { ethers, network, upgrades } from "hardhat";
|
||||
import { task } from "hardhat/config";
|
||||
import { TokenBridge } from "../../typechain-types";
|
||||
import { getTaskCliOrEnvValue } from "../../common/helpers/environmentHelper";
|
||||
import { getDeployedContractOnNetwork } from "../../common/helpers/readAddress";
|
||||
|
||||
/*
|
||||
*******************************************************************************************
|
||||
1. Deploy the TokenBridge and BridgedToken contracts on both networks and get the addresses
|
||||
2. Run this script on both addresses with the correct variables set.
|
||||
*******************************************************************************************
|
||||
SEPOLIA_PRIVATE_KEY=<key> \
|
||||
INFURA_API_KEY=<key> \
|
||||
npx hardhat setRemoteTokenBridge \
|
||||
--remote-token-bridge-address <address> \
|
||||
--token-bridge-address <address> \
|
||||
--remote-network sepolia \
|
||||
--network linea_sepolia
|
||||
*******************************************************************************************
|
||||
*/
|
||||
|
||||
task("setRemoteTokenBridge", "Sets the remoteTokenBridge address.")
|
||||
.addOptionalParam("remoteTokenBridgeAddress")
|
||||
.addOptionalParam("tokenBridgeAddress")
|
||||
.addParam("remoteNetwork")
|
||||
.setAction(async (taskArgs, hre) => {
|
||||
const ethers = hre.ethers;
|
||||
|
||||
let remoteTokenBridgeAddress = getTaskCliOrEnvValue(
|
||||
taskArgs,
|
||||
"remoteTokenBridgeAddress",
|
||||
"REMOTE_TOKEN_BRIDGE_ADDRESS",
|
||||
);
|
||||
|
||||
let tokenBridgeAddress = getTaskCliOrEnvValue(taskArgs, "tokenBridgeAddress", "TOKEN_BRIDGE_ADDRESS");
|
||||
|
||||
if (!tokenBridgeAddress) {
|
||||
tokenBridgeAddress = await getDeployedContractOnNetwork(hre.network.name, "TokenBridge");
|
||||
if (!tokenBridgeAddress) {
|
||||
throw "tokenBridgeAddress is undefined";
|
||||
}
|
||||
}
|
||||
|
||||
if (!remoteTokenBridgeAddress) {
|
||||
remoteTokenBridgeAddress = await getDeployedContractOnNetwork(taskArgs.remoteNetwork, "TokenBridge");
|
||||
if (!remoteTokenBridgeAddress) {
|
||||
throw "remoteTokenBridgeAddress is undefined";
|
||||
}
|
||||
}
|
||||
|
||||
const chainId = (await ethers.provider.getNetwork()).chainId;
|
||||
console.log(`Current network's chainId is ${chainId}`);
|
||||
|
||||
const TokenBridge = await ethers.getContractFactory("TokenBridge");
|
||||
const tokenBridge = TokenBridge.attach(tokenBridgeAddress) as TokenBridge;
|
||||
const tx = await tokenBridge.setRemoteTokenBridge(remoteTokenBridgeAddress);
|
||||
|
||||
await tx.wait();
|
||||
|
||||
console.log(`RemoteTokenBridge set for the TokenBridge on: ${hre.network.name}`);
|
||||
});
|
||||
@@ -19,6 +19,12 @@ export async function deployTokenBridge(messageServiceAddress: string, verbose =
|
||||
// Deploying TokenBridges
|
||||
const TokenBridgeFactory = await ethers.getContractFactory("TokenBridge");
|
||||
|
||||
await upgrades.deployImplementation(TokenBridgeFactory);
|
||||
// When upgrade OZ contracts to 5.X and Hardhat Upgrades plugin to 3.X, remove the line below (as deployProxyAdmin will be deprecated)
|
||||
await upgrades.deployProxyAdmin(owner);
|
||||
|
||||
// deployProxy will implicitly do deployImplementation and deployProxyAdmin if they have not previously been done.
|
||||
// This will mess with our nonce calculation for the counterfactual address of l2TokenBridge, so we prevent these steps from being handled implicitly in deployProxy.
|
||||
const l1TokenBridge = (await upgrades.deployProxy(TokenBridgeFactory, [
|
||||
{
|
||||
defaultAdmin: owner.address,
|
||||
@@ -27,6 +33,7 @@ export async function deployTokenBridge(messageServiceAddress: string, verbose =
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[1],
|
||||
reservedTokens: [],
|
||||
remoteSender: ethers.getCreateAddress({ from: await owner.getAddress(), nonce: 1 + (await owner.getNonce()) }), // Counterfactual address of l2TokenBridge
|
||||
roleAddresses: roleAddresses,
|
||||
pauseTypeRoles: pauseTypeRoles,
|
||||
unpauseTypeRoles: unpauseTypeRoles,
|
||||
@@ -45,6 +52,7 @@ export async function deployTokenBridge(messageServiceAddress: string, verbose =
|
||||
sourceChainId: chainIds[1],
|
||||
targetChainId: chainIds[0],
|
||||
reservedTokens: [],
|
||||
remoteSender: await l1TokenBridge.getAddress(),
|
||||
roleAddresses: roleAddresses,
|
||||
pauseTypeRoles: pauseTypeRoles,
|
||||
unpauseTypeRoles: unpauseTypeRoles,
|
||||
@@ -55,13 +63,6 @@ export async function deployTokenBridge(messageServiceAddress: string, verbose =
|
||||
console.log("L2TokenBridge deployed, at address:", await l2TokenBridge.getAddress());
|
||||
}
|
||||
|
||||
// Setting reciprocal addresses of TokenBridges
|
||||
await l1TokenBridge.setRemoteTokenBridge(await l2TokenBridge.getAddress());
|
||||
await l2TokenBridge.setRemoteTokenBridge(await l1TokenBridge.getAddress());
|
||||
if (verbose) {
|
||||
console.log("Reciprocal addresses of TokenBridges set");
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
console.log("Deployment finished");
|
||||
}
|
||||
|
||||
@@ -39,14 +39,11 @@ contract TokenBridge is
|
||||
using SafeERC20Upgradeable for IERC20Upgradeable;
|
||||
|
||||
/// @dev This is the ABI version and not the reinitialize version.
|
||||
string public constant CONTRACT_VERSION = "1.0";
|
||||
string public constant CONTRACT_VERSION = "1.1";
|
||||
|
||||
/// @notice Role used for setting the message service address.
|
||||
bytes32 public constant SET_MESSAGE_SERVICE_ROLE = keccak256("SET_MESSAGE_SERVICE_ROLE");
|
||||
|
||||
/// @notice Role used for setting the remote token bridge address.
|
||||
bytes32 public constant SET_REMOTE_TOKENBRIDGE_ROLE = keccak256("SET_REMOTE_TOKENBRIDGE_ROLE");
|
||||
|
||||
/// @notice Role used for setting a reserved token address.
|
||||
bytes32 public constant SET_RESERVED_TOKEN_ROLE = keccak256("SET_RESERVED_TOKEN_ROLE");
|
||||
|
||||
@@ -171,6 +168,7 @@ contract TokenBridge is
|
||||
|
||||
tokenBeacon = _initializationData.tokenBeacon;
|
||||
if (_initializationData.sourceChainId == _initializationData.targetChainId) revert SourceChainSameAsTargetChain();
|
||||
_setRemoteSender(_initializationData.remoteSender);
|
||||
sourceChainId = _initializationData.sourceChainId;
|
||||
targetChainId = _initializationData.targetChainId;
|
||||
|
||||
@@ -186,38 +184,6 @@ contract TokenBridge is
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Sets permissions for a list of addresses and their roles as well as initialises the PauseManager pauseType:role mappings.
|
||||
* @dev This function is a reinitializer and can only be called once per version. Should be called using an upgradeAndCall transaction to the ProxyAdmin.
|
||||
* @param _defaultAdmin The default admin account's address.
|
||||
* @param _roleAddresses The list of addresses and roles to assign permissions to.
|
||||
* @param _pauseTypeRoles The list of pause types to associate with roles.
|
||||
* @param _unpauseTypeRoles The list of unpause types to associate with roles.
|
||||
*/
|
||||
function reinitializePauseTypesAndPermissions(
|
||||
address _defaultAdmin,
|
||||
RoleAddress[] calldata _roleAddresses,
|
||||
PauseTypeRole[] calldata _pauseTypeRoles,
|
||||
PauseTypeRole[] calldata _unpauseTypeRoles
|
||||
) external reinitializer(2) {
|
||||
if (_defaultAdmin == address(0)) {
|
||||
revert ZeroAddressNotAllowed();
|
||||
}
|
||||
|
||||
_grantRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
|
||||
|
||||
assembly {
|
||||
/// @dev Wiping the storage slot 101 of _owner as it is replaced by AccessControl and there is now the ERC165 __gap in its place.
|
||||
sstore(101, 0)
|
||||
/// @dev Wiping the storage slot 213 of _status as it is replaced by ReentrancyGuardUpgradeable at slot 1.
|
||||
sstore(213, 0)
|
||||
}
|
||||
|
||||
__ReentrancyGuard_init();
|
||||
__PauseManager_init(_pauseTypeRoles, _unpauseTypeRoles);
|
||||
__Permissions_init(_roleAddresses);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice This function is the single entry point to bridge tokens to the
|
||||
* other chain, both for native and already bridged tokens. You can use it
|
||||
@@ -416,17 +382,6 @@ contract TokenBridge is
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets the address of the remote token bridge. Can only be called once.
|
||||
* @dev SET_REMOTE_TOKENBRIDGE_ROLE is required to execute.
|
||||
* @param _remoteTokenBridge The address of the remote token bridge to be set.
|
||||
*/
|
||||
function setRemoteTokenBridge(address _remoteTokenBridge) external onlyRole(SET_REMOTE_TOKENBRIDGE_ROLE) {
|
||||
if (remoteSender != EMPTY) revert RemoteTokenBridgeAlreadySet(remoteSender);
|
||||
_setRemoteSender(_remoteTokenBridge);
|
||||
emit RemoteTokenBridgeSet(_remoteTokenBridge, msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Deploy a new EC20 contract for bridged token using a beacon proxy pattern.
|
||||
* To adapt to future requirements, Linea can update the implementation of
|
||||
|
||||
@@ -17,6 +17,7 @@ interface ITokenBridge {
|
||||
* @param tokenBeacon The address of the tokenBeacon.
|
||||
* @param sourceChainId The source chain id of the current layer.
|
||||
* @param targetChainId The target chaind id of the targeted layer.
|
||||
* @param remoteSender Address of the remote token bridge.
|
||||
* @param reservedTokens The list of reserved tokens to be set.
|
||||
* @param roleAddresses The list of addresses and roles to assign permissions to.
|
||||
* @param pauseTypeRoles The list of pause types to associate with roles.
|
||||
@@ -28,6 +29,7 @@ interface ITokenBridge {
|
||||
address tokenBeacon;
|
||||
uint256 sourceChainId;
|
||||
uint256 targetChainId;
|
||||
address remoteSender;
|
||||
address[] reservedTokens;
|
||||
IPermissionsManager.RoleAddress[] roleAddresses;
|
||||
IPauseManager.PauseTypeRole[] pauseTypeRoles;
|
||||
@@ -294,12 +296,6 @@ interface ITokenBridge {
|
||||
*/
|
||||
function setReserved(address _token) external;
|
||||
|
||||
/**
|
||||
* @dev Sets the address of the remote token bridge. Can only be called once.
|
||||
* @param _remoteTokenBridge The address of the remote token bridge to be set.
|
||||
*/
|
||||
function setRemoteTokenBridge(address _remoteTokenBridge) external;
|
||||
|
||||
/**
|
||||
* @dev Removes a token from the reserved list.
|
||||
* @param _token The address of the token to be removed from the reserved list.
|
||||
|
||||
@@ -5,7 +5,7 @@ import { deployTokenBridgeWithMockMessaging } from "../../../../scripts/tokenBri
|
||||
import { deployTokens } from "../../../../scripts/tokenBridge/test/deployTokens";
|
||||
import { BridgedToken, TestTokenBridge } from "../../../../typechain-types";
|
||||
import { getPermitData } from "./utils/permitHelper";
|
||||
import { Contract, ZeroAddress } from "ethers";
|
||||
import { Contract } from "ethers";
|
||||
import {
|
||||
ADDRESS_ZERO,
|
||||
COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE,
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
REMOVE_RESERVED_TOKEN_ROLE,
|
||||
SET_CUSTOM_CONTRACT_ROLE,
|
||||
SET_MESSAGE_SERVICE_ROLE,
|
||||
SET_REMOTE_TOKENBRIDGE_ROLE,
|
||||
SET_RESERVED_TOKEN_ROLE,
|
||||
UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE,
|
||||
pauseTypeRoles,
|
||||
@@ -80,6 +79,7 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[1],
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [],
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: [],
|
||||
@@ -102,6 +102,7 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[1],
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [],
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: [],
|
||||
@@ -120,6 +121,7 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: ADDRESS_ZERO,
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[1],
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [],
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: [],
|
||||
@@ -138,6 +140,26 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[1],
|
||||
remoteSender: ADDRESS_ZERO,
|
||||
reservedTokens: [],
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: [],
|
||||
unpauseTypeRoles: [],
|
||||
},
|
||||
]),
|
||||
"ZeroAddressNotAllowed",
|
||||
);
|
||||
|
||||
await expectRevertWithCustomError(
|
||||
TokenBridge,
|
||||
upgrades.deployProxy(TokenBridge, [
|
||||
{
|
||||
defaultAdmin: PLACEHOLDER_ADDRESS,
|
||||
messageService: PLACEHOLDER_ADDRESS,
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[1],
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [PLACEHOLDER_ADDRESS, ADDRESS_ZERO],
|
||||
roleAddresses: [
|
||||
{ addressWithRole: user.address, role: SET_RESERVED_TOKEN_ROLE },
|
||||
@@ -159,6 +181,7 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[1],
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [PLACEHOLDER_ADDRESS],
|
||||
roleAddresses: [
|
||||
{ addressWithRole: ADDRESS_ZERO, role: SET_RESERVED_TOKEN_ROLE },
|
||||
@@ -185,6 +208,7 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: 0,
|
||||
targetChainId: chainIds[1],
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [],
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: [],
|
||||
@@ -203,6 +227,7 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: 0,
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [],
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: [],
|
||||
@@ -226,6 +251,7 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[0],
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [],
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: [],
|
||||
@@ -249,6 +275,7 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[1],
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [],
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: [],
|
||||
@@ -268,6 +295,7 @@ describe("TokenBridge", function () {
|
||||
tokenBeacon: PLACEHOLDER_ADDRESS,
|
||||
sourceChainId: SupportedChainIds.SEPOLIA,
|
||||
targetChainId: SupportedChainIds.LINEA_TESTNET,
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
reservedTokens: [],
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: [],
|
||||
@@ -740,6 +768,7 @@ describe("TokenBridge", function () {
|
||||
sourceChainId: chainIds[0],
|
||||
targetChainId: chainIds[1],
|
||||
reservedTokens: [CUSTOM_ADDRESS],
|
||||
remoteSender: PLACEHOLDER_ADDRESS,
|
||||
roleAddresses: [],
|
||||
pauseTypeRoles: pauseTypeRoles,
|
||||
unpauseTypeRoles: unpauseTypeRoles,
|
||||
@@ -945,24 +974,6 @@ describe("TokenBridge", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("setRemoteTokenBridge", function () {
|
||||
it("Should revert if remoteTokenBridge has not been initialized", async function () {
|
||||
const { owner, l1TokenBridge } = await loadFixture(deployContractsFixture);
|
||||
await expect(
|
||||
l1TokenBridge.connect(owner).setRemoteTokenBridge(await l1TokenBridge.getAddress()),
|
||||
).to.revertedWithCustomError(l1TokenBridge, "RemoteTokenBridgeAlreadySet");
|
||||
});
|
||||
|
||||
it("Should revert if called by non-owner", async function () {
|
||||
const { user, l1TokenBridge } = await loadFixture(deployContractsFixture);
|
||||
|
||||
await expectRevertWithReason(
|
||||
l1TokenBridge.connect(user).setRemoteTokenBridge(await l1TokenBridge.getAddress()),
|
||||
buildAccessErrorMessage(user, SET_REMOTE_TOKENBRIDGE_ROLE),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setDeployed", function () {
|
||||
it("Should revert if not called by the messageService", async function () {
|
||||
const { user, l1TokenBridge } = await loadFixture(deployContractsFixture);
|
||||
@@ -989,42 +1000,6 @@ describe("TokenBridge", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("reinitializePauseTypesAndPermissions", function () {
|
||||
it("Should revert with ZeroAddressNotAllowed when addressWithRole is zero address in reinitializePauseTypesAndPermissions", async function () {
|
||||
const { owner, l1TokenBridge } = await loadFixture(deployContractsFixture);
|
||||
|
||||
const roleAddresses = [{ addressWithRole: ZeroAddress, role: SET_RESERVED_TOKEN_ROLE }];
|
||||
|
||||
await expectRevertWithCustomError(
|
||||
l1TokenBridge,
|
||||
l1TokenBridge.reinitializePauseTypesAndPermissions(
|
||||
owner.address,
|
||||
roleAddresses,
|
||||
pauseTypeRoles,
|
||||
unpauseTypeRoles,
|
||||
),
|
||||
"ZeroAddressNotAllowed",
|
||||
);
|
||||
});
|
||||
|
||||
it("Should revert with ZeroAddressNotAllowed when default admin is zero address", async function () {
|
||||
const { owner, l1TokenBridge } = await loadFixture(deployContractsFixture);
|
||||
|
||||
const roleAddresses = [{ addressWithRole: owner.address, role: SET_RESERVED_TOKEN_ROLE }];
|
||||
|
||||
await expectRevertWithCustomError(
|
||||
l1TokenBridge,
|
||||
l1TokenBridge.reinitializePauseTypesAndPermissions(
|
||||
ZeroAddress, //owner is set to zeroaddress
|
||||
roleAddresses,
|
||||
pauseTypeRoles,
|
||||
unpauseTypeRoles,
|
||||
),
|
||||
"ZeroAddressNotAllowed",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("TokenBridge Upgradeable Tests", function () {
|
||||
it.skip("Should deploy and manually upgrade the TokenBridge contract", async function () {
|
||||
// Deploy V1 from artifact
|
||||
|
||||
@@ -56,7 +56,6 @@ export const UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = generateKeccak256(
|
||||
["UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"],
|
||||
true,
|
||||
);
|
||||
export const SET_REMOTE_TOKENBRIDGE_ROLE = generateKeccak256(["string"], ["SET_REMOTE_TOKENBRIDGE_ROLE"], true);
|
||||
export const SET_RESERVED_TOKEN_ROLE = generateKeccak256(["string"], ["SET_RESERVED_TOKEN_ROLE"], true);
|
||||
export const REMOVE_RESERVED_TOKEN_ROLE = generateKeccak256(["string"], ["REMOVE_RESERVED_TOKEN_ROLE"], true);
|
||||
export const SET_CUSTOM_CONTRACT_ROLE = generateKeccak256(["string"], ["SET_CUSTOM_CONTRACT_ROLE"], true);
|
||||
|
||||
@@ -3,7 +3,7 @@ import assert from "assert";
|
||||
import { AbstractSigner, BaseContract, BlockTag, TransactionReceipt, TransactionRequest, Wallet, ethers } from "ethers";
|
||||
import path from "path";
|
||||
import { exec } from "child_process";
|
||||
import { L2MessageServiceV1 as L2MessageService, TokenBridgeV1 as TokenBridge, LineaRollupV6 } from "../typechain";
|
||||
import { L2MessageServiceV1 as L2MessageService, TokenBridgeV1_1 as TokenBridge, LineaRollupV6 } from "../typechain";
|
||||
import {
|
||||
PayableOverrides,
|
||||
TypedContractEvent,
|
||||
|
||||
@@ -26,18 +26,10 @@ export default async (): Promise<void> => {
|
||||
};
|
||||
|
||||
async function configureOnceOffPrerequisities() {
|
||||
const l1AccountManager = config.getL1AccountManager();
|
||||
const l2AccountManager = config.getL2AccountManager();
|
||||
|
||||
const account = config.getL1AccountManager().whaleAccount(0);
|
||||
const l2Account = config.getL2AccountManager().whaleAccount(0);
|
||||
const lineaRollup = config.getLineaRollupContract(account);
|
||||
|
||||
const l1TokenBridge = config.getL1TokenBridgeContract();
|
||||
const l2TokenBridge = config.getL2TokenBridgeContract();
|
||||
const l1SecurityCouncil = l1AccountManager.whaleAccount(3);
|
||||
const l2SecurityCouncil = l2AccountManager.whaleAccount(3);
|
||||
|
||||
const [l1AccountNonce, l2AccountNonce] = await Promise.all([account.getNonce(), l2Account.getNonce()]);
|
||||
|
||||
const fee = etherToWei("3");
|
||||
@@ -58,16 +50,6 @@ async function configureOnceOffPrerequisities() {
|
||||
nonce: l1AccountNonce + 1,
|
||||
})
|
||||
).wait(),
|
||||
(
|
||||
await l1TokenBridge.connect(l1SecurityCouncil).setRemoteTokenBridge(await l2TokenBridge.getAddress(), {
|
||||
gasPrice: ethers.parseUnits("300", "gwei"),
|
||||
})
|
||||
).wait(),
|
||||
(
|
||||
await l2TokenBridge.connect(l2SecurityCouncil).setRemoteTokenBridge(await l1TokenBridge.getAddress(), {
|
||||
gasPrice: ethers.parseUnits("300", "gwei"),
|
||||
})
|
||||
).wait(),
|
||||
]);
|
||||
|
||||
logger.info(`L1 Dummy contract deployed. address=${await dummyContract.getAddress()}`);
|
||||
|
||||
@@ -17,8 +17,8 @@ import {
|
||||
TestContract__factory,
|
||||
TestERC20,
|
||||
TestERC20__factory,
|
||||
TokenBridgeV1 as TokenBridge,
|
||||
TokenBridgeV1__factory as TokenBridge__factory,
|
||||
TokenBridgeV1_1 as TokenBridge,
|
||||
TokenBridgeV1_1__factory as TokenBridge__factory,
|
||||
} from "../../typechain";
|
||||
import { AccountManager } from "./accounts/account-manager";
|
||||
|
||||
|
||||
@@ -48,26 +48,28 @@ deploy-token-bridge-l1:
|
||||
# WARNING: FOR LOCAL DEV ONLY - DO NOT REUSE THESE KEYS ELSEWHERE
|
||||
cd contracts/; \
|
||||
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
|
||||
REMOTE_DEPLOYER_ADDRESS=0x1B9AbEeC3215D8AdE8a33607f2cF0f4F60e5F0D0 \
|
||||
RPC_URL=http:\\localhost:8445/ \
|
||||
REMOTE_CHAIN_ID=1337 \
|
||||
TOKEN_BRIDGE_L1=true \
|
||||
L1_TOKEN_BRIDGE_SECURITY_COUNCIL=0x90F79bf6EB2c4f870365E785982E1f101E93b906 \
|
||||
L2MESSAGESERVICE_ADDRESS=0xe537D669CA013d86EBeF1D64e40fC74CADC91987 \
|
||||
LINEA_ROLLUP_ADDRESS=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9 \
|
||||
npx ts-node local-deployments-artifacts/deployBridgedTokenAndTokenBridgeV1.ts
|
||||
npx ts-node local-deployments-artifacts/deployBridgedTokenAndTokenBridgeV1_1.ts
|
||||
|
||||
deploy-token-bridge-l2:
|
||||
# WARNING: FOR LOCAL DEV ONLY - DO NOT REUSE THESE KEYS ELSEWHERE
|
||||
cd contracts/; \
|
||||
SAVE_ADDRESS=true \
|
||||
PRIVATE_KEY=0x1dd171cec7e2995408b5513004e8207fe88d6820aeff0d82463b3e41df251aae \
|
||||
REMOTE_DEPLOYER_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 \
|
||||
RPC_URL=http:\\localhost:8545/ \
|
||||
REMOTE_CHAIN_ID=31648428 \
|
||||
TOKEN_BRIDGE_L1=false \
|
||||
L2_TOKEN_BRIDGE_SECURITY_COUNCIL=0xf17f52151EbEF6C7334FAD080c5704D77216b732 \
|
||||
L2MESSAGESERVICE_ADDRESS=0xe537D669CA013d86EBeF1D64e40fC74CADC91987 \
|
||||
LINEA_ROLLUP_ADDRESS=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9 \
|
||||
npx ts-node local-deployments-artifacts/deployBridgedTokenAndTokenBridgeV1.ts
|
||||
npx ts-node local-deployments-artifacts/deployBridgedTokenAndTokenBridgeV1_1.ts
|
||||
|
||||
deploy-l1-test-erc20:
|
||||
# WARNING: FOR LOCAL DEV ONLY - DO NOT REUSE THESE KEYS ELSEWHERE
|
||||
|
||||
Reference in New Issue
Block a user