diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1e3bdcba..9da0d3e5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,9 @@ name: Default on: + push: + branches: + - main # To trigger coverage updates of `main` on Codecov pull_request: workflow_call: inputs: @@ -48,7 +51,7 @@ jobs: SEPOLIA_RPC_URL: ${{ inputs.SEPOLIA_RPC_URL || vars.SEPOLIA_RPC_URL }} ARBITRUM_SEPOLIA_RPC_URL: ${{ inputs.ARBITRUM_SEPOLIA_RPC_URL || vars.ARBITRUM_SEPOLIA_RPC_URL }} run: make generate-coverage - + - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v5 with: diff --git a/README.md b/README.md index a56b1dc6..898a39e6 100644 --- a/README.md +++ b/README.md @@ -339,13 +339,13 @@ The scripts automatically calculate these fees and include them in the transacti ## How to release: - -* First, deploy on Testnets and make sure all tests are ok. -* Create a release branch `release/X.X.X` that starts from the `main` branch. - - Note that GitHub environments `arbitrum` and `ethereum` can only be used with `release/*` branches. The `main` branch cannot be used as the CI will not be able to commit deployment artifacts. -* Commit required changes (salt, ...) -* Go to "Actions" section on GitHub -* Trigger `Deploy contracts` job and choose the correct release branch and the target Github environment. +> **Note**:
+> Always deploy and validate on the Testnet first! + +* Go to "Actions" section on GitHub. +* Trigger the `Deploy contracts` job then choose the correct deployment branch and the target GitHub environment. + +Note that production GitHub environments `arbitrum` and `ethereum` can only be used with the `main` branch. ## TODO diff --git a/docs/soldoc/src/README.md b/docs/soldoc/src/README.md index a56b1dc6..898a39e6 100644 --- a/docs/soldoc/src/README.md +++ b/docs/soldoc/src/README.md @@ -339,13 +339,13 @@ The scripts automatically calculate these fees and include them in the transacti ## How to release: - -* First, deploy on Testnets and make sure all tests are ok. -* Create a release branch `release/X.X.X` that starts from the `main` branch. - - Note that GitHub environments `arbitrum` and `ethereum` can only be used with `release/*` branches. The `main` branch cannot be used as the CI will not be able to commit deployment artifacts. -* Commit required changes (salt, ...) -* Go to "Actions" section on GitHub -* Trigger `Deploy contracts` job and choose the correct release branch and the target Github environment. +> **Note**:
+> Always deploy and validate on the Testnet first! + +* Go to "Actions" section on GitHub. +* Trigger the `Deploy contracts` job then choose the correct deployment branch and the target GitHub environment. + +Note that production GitHub environments `arbitrum` and `ethereum` can only be used with the `main` branch. ## TODO diff --git a/script/RLCCrosschainToken.s.sol b/script/RLCCrosschainToken.s.sol index dbc30659..261d9f8e 100644 --- a/script/RLCCrosschainToken.s.sol +++ b/script/RLCCrosschainToken.s.sol @@ -56,8 +56,9 @@ contract Deploy is Script { address createxFactory, bytes32 createxSalt ) public returns (address) { - bytes memory initData = - abi.encodeWithSelector(RLCCrosschainToken.initialize.selector, name, symbol, initialAdmin, initialUpgrader); + bytes memory initData = abi.encodeWithSelector( + RLCCrosschainToken.initialize.selector, name, symbol, initialAdmin, initialUpgrader + ); return UUPSProxyDeployer.deployUsingCreateX("RLCCrosschainToken", "", initData, createxFactory, createxSalt); } } diff --git a/script/TransferAdminRole.s.sol b/script/TransferAdminRole.s.sol index e894538f..3e00ab88 100644 --- a/script/TransferAdminRole.s.sol +++ b/script/TransferAdminRole.s.sol @@ -5,8 +5,9 @@ pragma solidity ^0.8.22; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; -import {IAccessControlDefaultAdminRules} from - "@openzeppelin/contracts/access/extensions/IAccessControlDefaultAdminRules.sol"; +import { + IAccessControlDefaultAdminRules +} from "@openzeppelin/contracts/access/extensions/IAccessControlDefaultAdminRules.sol"; import {ConfigLib} from "./lib/ConfigLib.sol"; import {RLCLiquidityUnifier} from "../src/RLCLiquidityUnifier.sol"; import {RLCCrosschainToken} from "../src/RLCCrosschainToken.sol"; diff --git a/script/lib/ConfigLib.sol b/script/lib/ConfigLib.sol index 48107e45..dc36cfee 100644 --- a/script/lib/ConfigLib.sol +++ b/script/lib/ConfigLib.sol @@ -109,10 +109,10 @@ library ConfigLib { params.createxFactory = config.readAddress(".createxFactory"); params.rlcToken = getRLCTokenAddress(config, prefix); ( - params.rlcCrosschainTokenCreatexSalt, - params.rlcLiquidityUnifierCreatexSalt, - params.iexecLayerZeroBridgeCreatexSalt - ) = getAllCreatexParams(config, prefix); + params.rlcCrosschainTokenCreatexSalt, + params.rlcLiquidityUnifierCreatexSalt, + params.iexecLayerZeroBridgeCreatexSalt + ) = getAllCreatexParams(config, prefix); params.rlcCrosschainTokenAddress = getRLCCrosschainTokenAddress(config, prefix); params.rlcLiquidityUnifierAddress = getLiquidityUnifierAddress(config, prefix); params.approvalRequired = config.readBool(string.concat(prefix, ".approvalRequired")); @@ -161,8 +161,9 @@ library ConfigLib { */ function _validateJsonContent(string memory content) private pure { try vm.parseJson(content) { - // JSON is valid, proceed - } catch { + // JSON is valid, proceed + } + catch { console.log("Invalid JSON in config file"); revert("Invalid JSON format"); } diff --git a/script/lib/UUPSProxyDeployer.sol b/script/lib/UUPSProxyDeployer.sol index 9dfeb5b8..aa76afc5 100644 --- a/script/lib/UUPSProxyDeployer.sol +++ b/script/lib/UUPSProxyDeployer.sol @@ -32,14 +32,16 @@ library UUPSProxyDeployer { address createxFactory, bytes32 createxSalt ) internal returns (address) { - address implementation = - deployImplementationUsingCreateX(contractName, constructorData, createxFactory, createxSalt); - address proxy = ICreateX(createxFactory).deployCreate2AndInit( - createxSalt, - abi.encodePacked(type(ERC1967Proxy).creationCode, abi.encode(implementation, "")), // initCode - initializeData, - ICreateX.Values({constructorAmount: 0, initCallAmount: 0}) // values for CreateX + address implementation = deployImplementationUsingCreateX( + contractName, constructorData, createxFactory, createxSalt ); + address proxy = ICreateX(createxFactory) + .deployCreate2AndInit( + createxSalt, + abi.encodePacked(type(ERC1967Proxy).creationCode, abi.encode(implementation, "")), // initCode + initializeData, + ICreateX.Values({constructorAmount: 0, initCallAmount: 0}) // values for CreateX + ); console.log("UUPS Proxy deployed at:", proxy); return proxy; } diff --git a/src/RLCCrosschainToken.sol b/src/RLCCrosschainToken.sol index 73b73b82..629f0ed5 100644 --- a/src/RLCCrosschainToken.sol +++ b/src/RLCCrosschainToken.sol @@ -4,13 +4,16 @@ pragma solidity ^0.8.22; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; -import {AccessControlDefaultAdminRulesUpgradeable} from - "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlDefaultAdminRulesUpgradeable.sol"; +import { + AccessControlDefaultAdminRulesUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlDefaultAdminRulesUpgradeable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import {ERC20PermitUpgradeable} from - "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol"; -import {ERC20BridgeableUpgradeable} from - "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-ERC20BridgeableUpgradeable.sol"; +import { + ERC20PermitUpgradeable +} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol"; +import { + ERC20BridgeableUpgradeable +} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-ERC20BridgeableUpgradeable.sol"; import {ITokenSpender} from "./interfaces/ITokenSpender.sol"; /** @@ -101,7 +104,13 @@ contract RLCCrosschainToken is * @dev Authorizes upgrades of the proxy. It can only be called by * an account with the UPGRADER_ROLE. */ - function _authorizeUpgrade(address /*newImplementation*/ ) internal override onlyRole(UPGRADER_ROLE) {} + function _authorizeUpgrade( + address /*newImplementation*/ + ) + internal + override + onlyRole(UPGRADER_ROLE) + {} /** * Checks if the caller is a trusted token bridge that is allowed by iExec to call @@ -109,5 +118,12 @@ contract RLCCrosschainToken is * @dev This function is called by the modifier `onlyTokenBridge` in the * `ERC20BridgeableUpgradeable` contract. */ - function _checkTokenBridge(address /*caller*/ ) internal view override onlyRole(TOKEN_BRIDGE_ROLE) {} + function _checkTokenBridge( + address /*caller*/ + ) + internal + view + override + onlyRole(TOKEN_BRIDGE_ROLE) + {} } diff --git a/src/RLCLiquidityUnifier.sol b/src/RLCLiquidityUnifier.sol index a32f0702..a9849eed 100644 --- a/src/RLCLiquidityUnifier.sol +++ b/src/RLCLiquidityUnifier.sol @@ -5,8 +5,9 @@ pragma solidity ^0.8.22; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import {AccessControlDefaultAdminRulesUpgradeable} from - "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlDefaultAdminRulesUpgradeable.sol"; +import { + AccessControlDefaultAdminRulesUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlDefaultAdminRulesUpgradeable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol"; diff --git a/src/bridges/layerZero/IexecLayerZeroBridge.sol b/src/bridges/layerZero/IexecLayerZeroBridge.sol index ad810ea5..399ce2ed 100644 --- a/src/bridges/layerZero/IexecLayerZeroBridge.sol +++ b/src/bridges/layerZero/IexecLayerZeroBridge.sol @@ -7,8 +7,9 @@ import {OFTCoreUpgradeable} from "@layerzerolabs/oft-evm-upgradeable/contracts/o import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import {AccessControlDefaultAdminRulesUpgradeable} from - "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlDefaultAdminRulesUpgradeable.sol"; +import { + AccessControlDefaultAdminRulesUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlDefaultAdminRulesUpgradeable.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {DualPausableUpgradeable} from "../utils/DualPausableUpgradeable.sol"; import {IIexecLayerZeroBridge} from "../../interfaces/IIexecLayerZeroBridge.sol"; @@ -312,7 +313,11 @@ contract IexecLayerZeroBridge is * @param amountLD The amount of tokens to mint (in local decimals) * @return amountReceivedLD The amount of tokens actually minted */ - function _credit(address to, uint256 amountLD, uint32 /*_srcEid*/ ) + function _credit( + address to, + uint256 amountLD, + uint32 /*_srcEid*/ + ) internal override whenNotPaused diff --git a/src/bridges/utils/DualPausableUpgradeable.sol b/src/bridges/utils/DualPausableUpgradeable.sol index e7bacf10..f2dfbd57 100644 --- a/src/bridges/utils/DualPausableUpgradeable.sol +++ b/src/bridges/utils/DualPausableUpgradeable.sol @@ -93,6 +93,7 @@ abstract contract DualPausableUpgradeable is PausableUpgradeable { //slither-disable-start naming-convention //slither-disable-start dead-code function __DualPausable_init_unchained() internal onlyInitializing {} + //slither-disable-end naming-convention //slither-disable-end dead-code diff --git a/test/e2e/IexecLayerZeroBridgeDeployScript.t.sol b/test/e2e/IexecLayerZeroBridgeDeployScript.t.sol index 6106159d..432368eb 100644 --- a/test/e2e/IexecLayerZeroBridgeDeployScript.t.sol +++ b/test/e2e/IexecLayerZeroBridgeDeployScript.t.sol @@ -41,15 +41,13 @@ contract IexecLayerZeroBridgeDeployScriptTest is Test { // Setup Ethereum Mainnet fork vm.selectFork(sepoliaFork); - rlcLiquidityUnifier = new RLCLiquidityUnifierDeployScript().deploy( - params.rlcToken, admin, upgrader, params.createxFactory, keccak256("salt") - ); + rlcLiquidityUnifier = new RLCLiquidityUnifierDeployScript() + .deploy(params.rlcToken, admin, upgrader, params.createxFactory, keccak256("salt")); // Setup Arbitrum Sepolia fork vm.selectFork(arbitrumSepoliaFork); - rlcCrosschainToken = new RLCCrosschainTokenDeployScript().deploy( - "iEx.ec Network Token", "RLC", admin, admin, params.createxFactory, salt - ); + rlcCrosschainToken = new RLCCrosschainTokenDeployScript() + .deploy("iEx.ec Network Token", "RLC", admin, admin, params.createxFactory, salt); //Add label to make logs more readable vm.label(address(rlcCrosschainToken), "rlcCrosschainToken"); diff --git a/test/units/RLCCrosschainToken.t.sol b/test/units/RLCCrosschainToken.t.sol index 4da2b9c8..95892ae0 100644 --- a/test/units/RLCCrosschainToken.t.sol +++ b/test/units/RLCCrosschainToken.t.sol @@ -36,9 +36,8 @@ contract RLCCrosschainTokenTest is Test { function setUp() public { rlcCrosschainToken = RLCCrosschainToken( - new RLCCrosschainTokenDeployScript().deploy( - "iEx.ec Network Token", "RLC", admin, upgrader, address(new CreateX()), keccak256("salt") - ) + new RLCCrosschainTokenDeployScript() + .deploy("iEx.ec Network Token", "RLC", admin, upgrader, address(new CreateX()), keccak256("salt")) ); bridgeTokenRoleId = rlcCrosschainToken.TOKEN_BRIDGE_ROLE(); diff --git a/test/units/RLCLiquidityUnifier.t.sol b/test/units/RLCLiquidityUnifier.t.sol index 835a0bfb..30cb2653 100644 --- a/test/units/RLCLiquidityUnifier.t.sol +++ b/test/units/RLCLiquidityUnifier.t.sol @@ -38,9 +38,8 @@ contract LiquidityUnifierTest is Test { function setUp() public { rlcToken = new RLCMock(); rlcLiquidityUnifier = RLCLiquidityUnifier( - new RLCLiquidityUnifierDeployScript().deploy( - address(rlcToken), admin, upgrader, address(new CreateX()), keccak256("salt") - ) + new RLCLiquidityUnifierDeployScript() + .deploy(address(rlcToken), admin, upgrader, address(new CreateX()), keccak256("salt")) ); rlcLiquidityUnifierAddress = address(rlcLiquidityUnifier); bridgeTokenRoleId = rlcLiquidityUnifier.TOKEN_BRIDGE_ROLE(); diff --git a/test/units/TransferAdminRoleScript.t.sol b/test/units/TransferAdminRoleScript.t.sol index 47810683..f38426c2 100644 --- a/test/units/TransferAdminRoleScript.t.sol +++ b/test/units/TransferAdminRoleScript.t.sol @@ -5,8 +5,9 @@ pragma solidity ^0.8.22; import {BeginTransferAdminRole, AcceptAdminRole} from "../../script/TransferAdminRole.s.sol"; import {TestHelperOz5} from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol"; -import {IAccessControlDefaultAdminRules} from - "@openzeppelin/contracts/access/extensions/IAccessControlDefaultAdminRules.sol"; +import { + IAccessControlDefaultAdminRules +} from "@openzeppelin/contracts/access/extensions/IAccessControlDefaultAdminRules.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {TestUtils} from "./utils/TestUtils.sol"; import {RLCLiquidityUnifier} from "../../src/RLCLiquidityUnifier.sol"; diff --git a/test/units/bridges/layerZero/IexecLayerZeroBridge.t.sol b/test/units/bridges/layerZero/IexecLayerZeroBridge.t.sol index 23e56b19..5b0d9fdf 100644 --- a/test/units/bridges/layerZero/IexecLayerZeroBridge.t.sol +++ b/test/units/bridges/layerZero/IexecLayerZeroBridge.t.sol @@ -7,8 +7,9 @@ import {MessagingFee, SendParam, IOFT} from "@layerzerolabs/oft-evm/contracts/in import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; import {IERC7802} from "@openzeppelin/contracts/interfaces/draft-IERC7802.sol"; import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; -import {IAccessControlDefaultAdminRules} from - "@openzeppelin/contracts/access/extensions/IAccessControlDefaultAdminRules.sol"; +import { + IAccessControlDefaultAdminRules +} from "@openzeppelin/contracts/access/extensions/IAccessControlDefaultAdminRules.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {TestHelperOz5} from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol"; diff --git a/test/units/bridges/layerZero/IexecLayerZeroBridgeConfigureScript.t.sol b/test/units/bridges/layerZero/IexecLayerZeroBridgeConfigureScript.t.sol index 265888a1..3869333e 100644 --- a/test/units/bridges/layerZero/IexecLayerZeroBridgeConfigureScript.t.sol +++ b/test/units/bridges/layerZero/IexecLayerZeroBridgeConfigureScript.t.sol @@ -9,8 +9,9 @@ import {IOAppCore} from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOApp import {IOAppOptionsType3} from "@layerzerolabs/oapp-evm/contracts/oapp/interfaces/IOAppOptionsType3.sol"; import {TestUtils} from "./../../utils/TestUtils.sol"; import {IexecLayerZeroBridge} from "../../../../src/bridges/layerZero/IexecLayerZeroBridge.sol"; -import {Configure as IexecLayerZeroBridgeConfigureScript} from - "../../../../script/bridges/layerZero/IexecLayerZeroBridge.s.sol"; +import { + Configure as IexecLayerZeroBridgeConfigureScript +} from "../../../../script/bridges/layerZero/IexecLayerZeroBridge.s.sol"; import {LayerZeroUtils} from "../../../../script/utils/LayerZeroUtils.sol"; // This test contract inherits from `Configure` script because we need the `msg.sender` to be the admin @@ -178,9 +179,8 @@ contract IexecLayerZeroBridgeUpgradeScriptTest is TestHelperOz5, IexecLayerZeroB "Expected authorizeBridgeIfNeeded to return true" ); assertTrue( - deployment.rlcLiquidityUnifier.hasRole( - deployment.rlcLiquidityUnifier.TOKEN_BRIDGE_ROLE(), sourceBridgeAddress - ), + deployment.rlcLiquidityUnifier + .hasRole(deployment.rlcLiquidityUnifier.TOKEN_BRIDGE_ROLE(), sourceBridgeAddress), "Expected bridge to have the role" ); // rlcCrosschainToken @@ -193,9 +193,8 @@ contract IexecLayerZeroBridgeUpgradeScriptTest is TestHelperOz5, IexecLayerZeroB "Expected authorizeBridgeIfNeeded to return true" ); assertTrue( - deployment.rlcCrosschainToken.hasRole( - deployment.rlcCrosschainToken.TOKEN_BRIDGE_ROLE(), targetBridgeAddress - ), + deployment.rlcCrosschainToken + .hasRole(deployment.rlcCrosschainToken.TOKEN_BRIDGE_ROLE(), targetBridgeAddress), "Expected bridge to have the role" ); vm.stopPrank(); @@ -212,9 +211,8 @@ contract IexecLayerZeroBridgeUpgradeScriptTest is TestHelperOz5, IexecLayerZeroB "Expected authorizeBridgeIfNeeded to return true" ); assertTrue( - deployment.rlcLiquidityUnifier.hasRole( - deployment.rlcLiquidityUnifier.TOKEN_BRIDGE_ROLE(), sourceBridgeAddress - ), + deployment.rlcLiquidityUnifier + .hasRole(deployment.rlcLiquidityUnifier.TOKEN_BRIDGE_ROLE(), sourceBridgeAddress), "Expected bridge to have the role" ); assertFalse( diff --git a/test/units/bridges/utils/DualPausableUpgradeable.t.sol b/test/units/bridges/utils/DualPausableUpgradeable.t.sol index e831fde9..e25e53ed 100644 --- a/test/units/bridges/utils/DualPausableUpgradeable.t.sol +++ b/test/units/bridges/utils/DualPausableUpgradeable.t.sol @@ -6,8 +6,9 @@ pragma solidity ^0.8.22; import {Test} from "forge-std/Test.sol"; import {DualPausableUpgradeable} from "../../../../src/bridges/utils/DualPausableUpgradeable.sol"; import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; -import {AccessControlDefaultAdminRulesUpgradeable} from - "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlDefaultAdminRulesUpgradeable.sol"; +import { + AccessControlDefaultAdminRulesUpgradeable +} from "@openzeppelin/contracts-upgradeable/access/extensions/AccessControlDefaultAdminRulesUpgradeable.sol"; /** * @title DualPausableUpgradeableTest diff --git a/test/units/utils/TestUtils.sol b/test/units/utils/TestUtils.sol index 390c7b23..387d7c23 100644 --- a/test/units/utils/TestUtils.sol +++ b/test/units/utils/TestUtils.sol @@ -77,9 +77,8 @@ library TestUtils { bytes32 salt ) private returns (RLCLiquidityUnifier) { return RLCLiquidityUnifier( - new RLCLiquidityUnifierDeployScript().deploy( - address(rlcToken), params.initialAdmin, params.initialUpgrader, createXFactory, salt - ) + new RLCLiquidityUnifierDeployScript() + .deploy(address(rlcToken), params.initialAdmin, params.initialUpgrader, createXFactory, salt) ); } @@ -121,9 +120,8 @@ library TestUtils { bytes32 salt ) private returns (RLCCrosschainToken) { return RLCCrosschainToken( - new RLCCrosschainTokenDeployScript().deploy( - name, symbol, params.initialAdmin, params.initialUpgrader, createXFactory, salt - ) + new RLCCrosschainTokenDeployScript() + .deploy(name, symbol, params.initialAdmin, params.initialUpgrader, createXFactory, salt) ); }