Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 0 additions & 46 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,32 +77,6 @@ deploy-all: # SOURCE_CHAIN, SOURCE_RPC, TARGET_CHAIN, TARGET_RPC, OPTIONS
@echo "⚠️ Please authorize bridges on RLCLiquidityUnifier and RLCCrosschainToken contracts."
# TODO verify contracts after deployment.

#
# High-level upgrade targets
#

upgrade-on-anvil:
$(MAKE) upgrade-all \
SOURCE_CHAIN=sepolia SOURCE_RPC=$(ANVIL_SEPOLIA_RPC_URL) \
TARGET_CHAIN=arbitrum_sepolia TARGET_RPC=$(ANVIL_ARBITRUM_SEPOLIA_RPC_URL)

upgrade-on-mainnets:
$(MAKE) upgrade-all \
SOURCE_CHAIN=ethereum SOURCE_RPC=$(ETHEREUM_RPC_URL) \
TARGET_CHAIN=arbitrum TARGET_RPC=$(ARBITRUM_RPC_URL) \
OPTIONS=--verify

# TODO : RLCMultichain and RLCLiquidityUnifier upgrades
upgrade-on-testnets:
$(MAKE) upgrade-all \
SOURCE_CHAIN=sepolia SOURCE_RPC=$(SEPOLIA_RPC_URL) \
TARGET_CHAIN=arbitrum_sepolia TARGET_RPC=$(ARBITRUM_SEPOLIA_RPC_URL) \
OPTIONS=--verify

upgrade-all: # SOURCE_CHAIN, SOURCE_RPC, TARGET_CHAIN, TARGET_RPC, OPTIONS
$(MAKE) upgrade-contract CONTRACT=bridges/layerZero/IexecLayerZeroBridge CHAIN=$(SOURCE_CHAIN) RPC_URL=$(SOURCE_RPC) OPTIONS=$(OPTIONS)
$(MAKE) upgrade-contract CONTRACT=bridges/layerZero/IexecLayerZeroBridge CHAIN=$(TARGET_CHAIN) RPC_URL=$(TARGET_RPC) OPTIONS=$(OPTIONS)

#
# Generic deployment targets
#
Expand All @@ -116,19 +90,6 @@ deploy-contract: # CONTRACT, CHAIN, RPC_URL, OPTIONS
--broadcast \
-vvv

#
# Generic upgrade targets
#

upgrade-contract: # CONTRACT, CHAIN, RPC_URL, OPTIONS
@echo "Upgrading $(CONTRACT) on $(CHAIN) with options: $(OPTIONS)"
CHAIN=$(CHAIN) forge script script/$(CONTRACT).s.sol:Upgrade \
--rpc-url $(RPC_URL) \
--account $(ACCOUNT) \
--broadcast \
$(OPTIONS) \
-vvv

#
# Generic configuration targets
#
Expand All @@ -142,13 +103,6 @@ configure-bridge: # SOURCE_CHAIN, TARGET_CHAIN, RPC_URL
--broadcast \
-vvv

#
# Individual upgrade targets
#

upgrade-layerzero-bridge: # CHAIN, RPC_URL
$(MAKE) upgrade-contract CONTRACT=bridges/layerZero/IexecLayerZeroBridge CHAIN=$(CHAIN) RPC_URL=$(RPC_URL)

#
# Bridge operations.
#
Expand Down
31 changes: 28 additions & 3 deletions script/RLCCrosschainToken.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
pragma solidity ^0.8.22;

import {Script} from "forge-std/Script.sol";
import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {Options} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {RLCCrosschainToken} from "../src/RLCCrosschainToken.sol";
import {UUPSProxyDeployer} from "./lib/UUPSProxyDeployer.sol";
import {UUPSProxyUtils} from "./lib/UUPSProxyUtils.sol";
import {ConfigLib} from "./lib/ConfigLib.sol";

/**
Expand Down Expand Up @@ -58,6 +58,31 @@ contract Deploy is Script {
) public returns (address) {
bytes memory initData =
abi.encodeWithSelector(RLCCrosschainToken.initialize.selector, name, symbol, initialAdmin, initialUpgrader);
return UUPSProxyDeployer.deployUsingCreateX("RLCCrosschainToken", "", initData, createxFactory, createxSalt);
return UUPSProxyUtils.deployUsingCreateX("RLCCrosschainToken", "", initData, createxFactory, createxSalt);
}
}

contract Upgrade is Script {
function run() external {
vm.startBroadcast();
upgrade({
proxyAddress: address(0), // Replace with the actual proxy address
contractName: "", // e.g., "ContractV2.sol:ContractV2"
constructorData: new bytes(0), // Replace with the actual constructor data
initData: new bytes(0) // Replace with the actual initialization data
});
vm.stopBroadcast();
}

// TODO add tests in `RLCCrosschainTokenUpgrade.t.sol`.
function upgrade(
address proxyAddress,
string memory contractName,
bytes memory constructorData,
bytes memory initData
) public {
Options memory opts;
opts.constructorData = constructorData;
UUPSProxyUtils.executeUpgrade(proxyAddress, contractName, initData, opts);
}
}
32 changes: 19 additions & 13 deletions script/RLCLiquidityUnifier.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
pragma solidity ^0.8.22;

import {Script} from "forge-std/Script.sol";
import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {Options} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {RLCLiquidityUnifier} from "../src/RLCLiquidityUnifier.sol";
import {UUPSProxyDeployer} from "./lib/UUPSProxyDeployer.sol";
import {UUPSProxyUtils} from "./lib/UUPSProxyUtils.sol";
import {ConfigLib} from "./lib/ConfigLib.sol";
import {UpgradeUtils} from "./lib/UpgradeUtils.sol";
/**
* Deployment script for the RLCLiquidityUnifier contract.
* It reads configuration from a JSON file and deploys the contract using CreateX.
Expand Down Expand Up @@ -57,25 +56,32 @@ contract Deploy is Script {
bytes memory constructorData = abi.encode(rlcToken);
bytes memory initData =
abi.encodeWithSelector(RLCLiquidityUnifier.initialize.selector, initialAdmin, initialUpgrader);
return UUPSProxyDeployer.deployUsingCreateX(
return UUPSProxyUtils.deployUsingCreateX(
"RLCLiquidityUnifier", constructorData, initData, createxFactory, createxSalt
);
}
}

contract Upgrade is Script {
function run() external {
string memory chain = vm.envString("CHAIN");
ConfigLib.CommonConfigParams memory commonParams = ConfigLib.readCommonConfig(chain);

vm.startBroadcast();
UpgradeUtils.UpgradeParams memory params = UpgradeUtils.UpgradeParams({
proxyAddress: commonParams.rlcLiquidityUnifierAddress,
constructorData: abi.encode(commonParams.rlcToken),
contractName: "RLCLiquidityUnifierV2Mock.sol:RLCLiquidityUnifierV2", // Would be production contract in real deployment
newStateVariable: 1000000 * 10 ** 9
upgrade({
proxyAddress: address(0), // Replace with the actual proxy address
contractName: "", // e.g., "ContractV2.sol:ContractV2"
constructorData: new bytes(0), // Replace with the actual constructor data
initData: new bytes(0) // Replace with the actual initialization data
});
UpgradeUtils.executeUpgrade(params);
vm.stopBroadcast();
}

function upgrade(
address proxyAddress,
string memory contractName,
bytes memory constructorData,
bytes memory initData
) public {
Options memory opts;
opts.constructorData = constructorData;
UUPSProxyUtils.executeUpgrade(proxyAddress, contractName, initData, opts);
}
}
50 changes: 32 additions & 18 deletions script/bridges/layerZero/IexecLayerZeroBridge.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
pragma solidity ^0.8.22;

import {Script} from "forge-std/Script.sol";
import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {Options} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {EnforcedOptionParam} from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OAppOptionsType3.sol";
import {OptionsBuilder} from "@layerzerolabs/oapp-evm/contracts/oapp/libs/OptionsBuilder.sol";
import {ConfigLib} from "./../../lib/ConfigLib.sol";
import {IexecLayerZeroBridge} from "../../../src/bridges/layerZero/IexecLayerZeroBridge.sol";
import {RLCLiquidityUnifier} from "../../../src/RLCLiquidityUnifier.sol";
import {RLCCrosschainToken} from "../../../src/RLCCrosschainToken.sol";
import {UUPSProxyDeployer} from "../../lib/UUPSProxyDeployer.sol";
import {UpgradeUtils} from "../../lib/UpgradeUtils.sol";
import {UUPSProxyUtils} from "../../lib/UUPSProxyUtils.sol";

contract Deploy is Script {
/**
Expand Down Expand Up @@ -53,12 +52,19 @@ contract Deploy is Script {
bytes memory initializeData = abi.encodeWithSelector(
IexecLayerZeroBridge.initialize.selector, initialAdmin, initialUpgrader, initialPauser
);
return UUPSProxyDeployer.deployUsingCreateX(
return UUPSProxyUtils.deployUsingCreateX(
"IexecLayerZeroBridge", constructorData, initializeData, createxFactory, createxSalt
);
}
}

/**
* This script is used to configure the IexecLayerZeroBridge contract on both source
* and target chains.
* It sets required LayerZero bridge config: peer address and enforced options.
* It also grants the bridge the necessary roles in the RLCCrosschainToken contract
* or RLCLiquidityUnifier contract, depending on the configuration.
*/
contract Configure is Script {
using OptionsBuilder for bytes;

Expand Down Expand Up @@ -93,22 +99,30 @@ contract Configure is Script {

contract Upgrade is Script {
function run() external {
string memory chain = vm.envString("CHAIN");
ConfigLib.CommonConfigParams memory commonParams = ConfigLib.readCommonConfig(chain);

// For testing purpose
uint256 newStateVariable = 1000000 * 10 ** 9;
address bridgeableToken = commonParams.approvalRequired
? commonParams.rlcLiquidityUnifierAddress
: commonParams.rlcCrosschainTokenAddress;
vm.startBroadcast();
UpgradeUtils.UpgradeParams memory params = UpgradeUtils.UpgradeParams({
proxyAddress: commonParams.iexecLayerZeroBridgeAddress,
constructorData: abi.encode(commonParams.approvalRequired, bridgeableToken, commonParams.lzEndpoint),
contractName: "IexecLayerZeroBridgeV2Mock.sol:IexecLayerZeroBridgeV2", // Would be production contract in real deployment
newStateVariable: newStateVariable
upgrade({
proxyAddress: address(0), // Replace with the actual proxy address
contractName: "", // e.g., "ContractV2.sol:ContractV2"
constructorData: new bytes(0), // Replace with the actual constructor data
initData: new bytes(0) // Replace with the actual initialization data
});
UpgradeUtils.executeUpgrade(params);
vm.stopBroadcast();
}

function upgrade(
address proxyAddress,
string memory contractName,
bytes memory constructorData,
bytes memory initData
) public {
Options memory opts;
opts.constructorData = constructorData;
// Ignore checks related to LayerZero contracts:
// - OAppSenderUpgradeable
// - OAppReceiverUpgradeable
// - OFTCoreUpgradeable
// - OAppCoreUpgradeable
opts.unsafeAllow = "constructor,state-variable-immutable,missing-initializer-call";
UUPSProxyUtils.executeUpgrade(proxyAddress, contractName, initData, opts);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import {Vm} from "forge-std/Vm.sol";
import {StdConstants} from "forge-std/StdConstants.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {ICreateX} from "@createx/contracts/ICreateX.sol";
import {Upgrades, Options} from "openzeppelin-foundry-upgrades/Upgrades.sol";

/**
* @notice Utility library for deploying UUPS proxy contracts and their implementations
* using the CreateX Factory.
*/
library UUPSProxyDeployer {
library UUPSProxyUtils {
/// @dev Reference to the VM cheat codes from forge-std
Vm private constant vm = StdConstants.VM;

Expand Down Expand Up @@ -64,4 +65,24 @@ library UUPSProxyDeployer {
console.log("Implementation deployed at:", implementation);
return implementation;
}

/**
* Upgrades a UUPS proxy contract to a new implementation.
* @param proxyAddress address of the UUPS proxy contract to upgrade
* @param contractName name of the contract to upgrade (e.g. "ContractV2.sol:ContractV2")
* @param opts options for the upgrade, such as unsafeAllow and others.
* @param initData initialization data for the proxy contract after upgrade
* @return newImplementation address of the new implementation contract
*/
function executeUpgrade(
address proxyAddress,
string memory contractName,
bytes memory initData,
Options memory opts
) internal returns (address newImplementation) {
Upgrades.upgradeProxy(proxyAddress, contractName, initData, opts);
newImplementation = Upgrades.getImplementationAddress(proxyAddress);
console.log("Upgraded", contractName, " proxy to new implementation", newImplementation);
return newImplementation;
}
}
52 changes: 0 additions & 52 deletions script/lib/UpgradeUtils.sol

This file was deleted.

18 changes: 8 additions & 10 deletions test/units/RLCLiquidityUnifierUpgrade.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
pragma solidity ^0.8.22;

import {TestHelperOz5} from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol";
import {RLCLiquidityUnifierV2} from "../../src/mocks/RLCLiquidityUnifierV2Mock.sol";
import {RLCLiquidityUnifier} from "../../src/RLCLiquidityUnifier.sol";
import {TestUtils} from "./utils/TestUtils.sol";
import {UpgradeUtils} from "../../script/lib/UpgradeUtils.sol";
import {UUPSProxyUtils} from "../../script/lib/UUPSProxyUtils.sol";
import {RLCMock} from "./mocks/RLCMock.sol";
import {RLCLiquidityUnifierV2} from "./mocks/RLCLiquidityUnifierV2Mock.sol";
import {Upgrade as RLCLiquidityUnifierUpgradeScript} from "../../script/RLCLiquidityUnifier.s.sol";

// TODO remove useless LZ setup (endpoint, ...).
contract RLCLiquidityUnifierUpgradeTest is TestHelperOz5 {
using TestUtils for *;

Expand Down Expand Up @@ -55,18 +57,14 @@ contract RLCLiquidityUnifierUpgradeTest is TestHelperOz5 {
assertTrue(rlcLiquidityUnifierV1.hasRole(rlcLiquidityUnifierV1.DEFAULT_ADMIN_ROLE(), admin));
assertTrue(rlcLiquidityUnifierV1.hasRole(rlcLiquidityUnifierV1.UPGRADER_ROLE(), upgrader));

// 3. Perform upgrade using UpgradeUtils directly
// 3. Perform upgrade
vm.startPrank(upgrader);

UpgradeUtils.UpgradeParams memory params = UpgradeUtils.UpgradeParams({
new RLCLiquidityUnifierUpgradeScript().upgrade({
proxyAddress: proxyAddress,
contractName: "RLCLiquidityUnifierV2Mock.sol:RLCLiquidityUnifierV2",
constructorData: abi.encode(rlcToken),
contractName: "RLCLiquidityUnifierV2Mock.sol:RLCLiquidityUnifierV2",
newStateVariable: NEW_STATE_VARIABLE
initData: abi.encodeWithSignature("initializeV2(uint256)", NEW_STATE_VARIABLE)
});

UpgradeUtils.executeUpgrade(params);

vm.stopPrank();

rlcLiquidityUnifierV2 = RLCLiquidityUnifierV2(proxyAddress);
Expand Down
Loading
Loading