Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: post-deploy v2 prep #96

Merged
merged 1 commit into from
Jan 21, 2025
Merged
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
15 changes: 15 additions & 0 deletions .env.deploy.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Deploy script environment variables
PRIVATE_KEY= # Private key of the deployer
DEPLOYER= # Address of the deployer
DEPLOYER_PROXY_NONCE= # Nonce of the deployer when creating the Wrapped M proxy
EXPECTED_PROXY= # Address of the expected Wrapped M proxy
M_TOKEN= # Address of the M token
REGISTRAR= # Address of the Registrar
EXCESS_DESTINATION= # Address of the Excess Destination
MIGRATION_ADMIN= # Address of the Migration Admin

# RPC URL to deploy to
DEPLOY_RPC_URL=

# Used for verifying contracts on Etherscan
ETHERSCAN_API_KEY=
8 changes: 4 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Localhost RPC URL
export LOCALHOST_RPC_URL=http://127.0.0.1:8545
LOCALHOST_RPC_URL=http://127.0.0.1:8545

# Mainnet RPC URLs
export MAINNET_RPC_URL=
MAINNET_RPC_URL=

# Testnet RPC URLs
export SEPOLIA_RPC_URL=
SEPOLIA_RPC_URL=

# Used for verifying contracts on Etherscan
export ETHERSCAN_API_KEY=
ETHERSCAN_API_KEY=
8 changes: 8 additions & 0 deletions .env.upgrade.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Mainnet upgrade script environment variables
PRIVATE_KEY= # Private key of the deployer

# Mainnet RPC URL to perform upgrade
MAINNET_RPC_URL=

# Used for verifying contracts on Etherscan
ETHERSCAN_API_KEY=
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"files": "*.sol",
"options": {
"bracketSpacing": true,
"compiler": "0.8.23",
"compiler": "0.8.26",
"parser": "solidity-parse",
"printWidth": 120,
"tabWidth": 4,
Expand Down
2 changes: 1 addition & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
],
"compiler-version": [
"error",
"0.8.23"
"0.8.26"
],
"comprehensive-interface": "off",
"const-name-snakecase": "off",
Expand Down
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ update:; forge update

# Deployment helpers
deploy:
FOUNDRY_PROFILE=production forge script script/DeployProduction.s.sol --skip src --skip test --rpc-url mainnet --slow --broadcast -vvv --verify
FOUNDRY_PROFILE=production forge script script/Deploy.s.sol --skip src --skip test --rpc-url ${DEPLOY_RPC_URL} --etherscan-api-key ${ETHERSCAN_API_KEY} --slow --broadcast -vvv --verify --show-standard-json-input

deploy-local:
FOUNDRY_PROFILE=production forge script script/DeployProduction.s.sol --skip src --skip test --rpc-url localhost --slow --broadcast -vvv
FOUNDRY_PROFILE=production forge script script/Deploy.s.sol --skip src --skip test --rpc-url localhost --slow --broadcast -vvv

deploy-upgrade:
FOUNDRY_PROFILE=production forge script script/DeployUpgradeMainnet.s.sol --skip src --skip test --rpc-url mainnet --slow --broadcast -vvv --verify --show-standard-json-input

# Run slither
slither :
Expand Down
8 changes: 3 additions & 5 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
gas_reports = ["*"]
gas_reports_ignore = []
ignored_error_codes = []
solc_version = "0.8.23"
solc_version = "0.8.26"
optimizer = true
optimizer_runs = 999999
verbosity = 3
block_number = 20_270_778
block_timestamp = 1_720_550_400
fork_block_number = 20_270_778
fork_block_number = 21_345_650
rpc_storage_caching = { chains = ["mainnet"], endpoints = "all" }
evm_version = "shanghai"
evm_version = "cancun"

[profile.production]
build_info = true
Expand Down
2 changes: 1 addition & 1 deletion lib/common
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mzero-labs/wrapped-m-token",
"version": "1.0.0",
"version": "2.0.0",
"description": "Wrapped M Token",
"author": "M^0 Labs <[email protected]>",
"repository": {
Expand Down
76 changes: 76 additions & 0 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.26;

import { Script, console2 } from "../lib/forge-std/src/Script.sol";

import { DeployBase } from "./DeployBase.sol";

contract DeployProduction is Script, DeployBase {
error DeployerMismatch(address expected, address actual);

error DeployerNonceTooHigh();

error UnexpectedDeployerNonce();

error CurrentNonceMismatch(uint64 expected, uint64 actual);

error ExpectedProxyMismatch(address expected, address actual);

error ResultingProxyMismatch(address expected, address actual);

function run() external {
address deployer_ = vm.rememberKey(vm.envUint("PRIVATE_KEY"));
address expectedDeployer_ = vm.envAddress("DEPLOYER");

uint64 deployerProxyNonce_ = uint64(vm.envUint("DEPLOYER_PROXY_NONCE"));

address expectedProxy_ = vm.envAddress("EXPECTED_PROXY");

console2.log("Deployer:", deployer_);

if (deployer_ != expectedDeployer_) revert DeployerMismatch(expectedDeployer_, deployer_);

uint64 currentNonce_ = vm.getNonce(deployer_);

uint64 startNonce_ = currentNonce_;
address implementation_;
address proxy_;

while (true) {
if (startNonce_ > deployerProxyNonce_) revert DeployerNonceTooHigh();

(implementation_, proxy_) = mockDeploy(deployer_, startNonce_);

if (proxy_ == expectedProxy_) break;

++startNonce_;
}

vm.startBroadcast(deployer_);

// Burn nonces until to `currentNonce_ == startNonce_`.
while (currentNonce_ < startNonce_) {
payable(deployer_).transfer(0);
++currentNonce_;
}

if (currentNonce_ != vm.getNonce(deployer_)) revert CurrentNonceMismatch(currentNonce_, vm.getNonce(deployer_));

if (currentNonce_ != startNonce_) revert UnexpectedDeployerNonce();

(implementation_, proxy_) = deploy(
vm.envAddress("M_TOKEN"),
vm.envAddress("REGISTRAR"),
vm.envAddress("EXCESS_DESTINATION"),
vm.envAddress("MIGRATION_ADMIN")
);

vm.stopBroadcast();

console2.log("Wrapped M Implementation address:", implementation_);
console2.log("Wrapped M Proxy address:", proxy_);

if (proxy_ != expectedProxy_) revert ResultingProxyMismatch(expectedProxy_, proxy_);
}
}
84 changes: 59 additions & 25 deletions script/DeployBase.sol
Original file line number Diff line number Diff line change
@@ -1,57 +1,91 @@
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.23;
pragma solidity 0.8.26;

import { ContractHelper } from "../lib/common/src/libs/ContractHelper.sol";
import { Proxy } from "../lib/common/src/Proxy.sol";

import { MigratorV1 } from "../src/MigratorV1.sol";
import { WrappedMToken } from "../src/WrappedMToken.sol";
import { Proxy } from "../src/Proxy.sol";

contract DeployBase {
/**
* @dev Deploys Wrapped M Token.
* @param mToken_ The address the M Token contract.
* @param migrationAdmin_ The address the Migration Admin.
* @return implementation_ The address of the deployed Wrapped M Token implementation.
* @return proxy_ The address of the deployed Wrapped M Token proxy.
* @param mToken_ The address of the M Token contract.
* @param registrar_ The address of the Registrar contract.
* @param excessDestination_ The address of the excess destination.
* @param migrationAdmin_ The address of the Migration Admin.
* @return implementation_ The address of the deployed Wrapped M Token implementation.
* @return proxy_ The address of the deployed Wrapped M Token proxy.
*/
function deploy(
address mToken_,
address registrar_,
address excessDestination_,
address migrationAdmin_
) public virtual returns (address implementation_, address proxy_) {
// Wrapped M token needs `mToken_` and `migrationAdmin_` addresses.
// Wrapped M token needs `mToken_`, `registrar_`, `excessDestination_`, and `migrationAdmin_` addresses.
// Proxy needs `implementation_` addresses.

implementation_ = address(new WrappedMToken(mToken_, migrationAdmin_));
implementation_ = address(new WrappedMToken(mToken_, registrar_, excessDestination_, migrationAdmin_));
proxy_ = address(new Proxy(implementation_));
}

function _getExpectedWrappedMTokenImplementation(
address deployer_,
uint256 deployerNonce_
) internal pure returns (address) {
return ContractHelper.getContractFrom(deployer_, deployerNonce_);
/**
* @dev Deploys Wrapped M Token components needed to upgrade an existing Wrapped M proxy.
* @param mToken_ The address of the M Token contract.
* @param registrar_ The address of the Registrar contract.
* @param excessDestination_ The address of the excess destination.
* @param migrationAdmin_ The address of the Migration Admin.
* @return implementation_ The address of the deployed Wrapped M Token implementation.
* @return migrator_ The address of the deployed Migrator.
*/
function deployUpgrade(
address mToken_,
address registrar_,
address excessDestination_,
address migrationAdmin_
) public virtual returns (address implementation_, address migrator_) {
// Wrapped M token needs `mToken_`, `registrar_`, `excessDestination_`, and `migrationAdmin_` addresses.
// Migrator needs `implementation_` addresses.

implementation_ = address(new WrappedMToken(mToken_, registrar_, excessDestination_, migrationAdmin_));
migrator_ = address(new MigratorV1(implementation_));
}

function getExpectedWrappedMTokenImplementation(
/**
* @dev Mock deploys Wrapped M Token, returning the would-be addresses.
* @param deployer_ The address of the deployer.
* @param deployerNonce_ The nonce of the deployer.
* @return implementation_ The address of the would-be Wrapped M Token implementation.
* @return proxy_ The address of the would-be Wrapped M Token proxy.
*/
function mockDeploy(
address deployer_,
uint256 deployerNonce_
) public pure virtual returns (address) {
return _getExpectedWrappedMTokenImplementation(deployer_, deployerNonce_);
}
) public view virtual returns (address implementation_, address proxy_) {
// Wrapped M token needs `mToken_`, `registrar_`, `excessDestination_`, and `migrationAdmin_` addresses.
// Proxy needs `implementation_` addresses.

function _getExpectedWrappedMTokenProxy(address deployer_, uint256 deployerNonce_) internal pure returns (address) {
return ContractHelper.getContractFrom(deployer_, deployerNonce_ + 1);
implementation_ = ContractHelper.getContractFrom(deployer_, deployerNonce_);
proxy_ = ContractHelper.getContractFrom(deployer_, deployerNonce_ + 1);
}

function getExpectedWrappedMTokenProxy(
/**
* @dev Mock deploys Wrapped M Token, returning the would-be addresses.
* @param deployer_ The address of the deployer.
* @param deployerNonce_ The nonce of the deployer.
* @return implementation_ The address of the would-be Wrapped M Token implementation.
* @return migrator_ The address of the would-be Migrator.
*/
function mockDeployUpgrade(
address deployer_,
uint256 deployerNonce_
) public pure virtual returns (address) {
return _getExpectedWrappedMTokenProxy(deployer_, deployerNonce_);
}
) public view virtual returns (address implementation_, address migrator_) {
// Wrapped M token needs `mToken_`, `registrar_`, `excessDestination_`, and `migrationAdmin_` addresses.
// Migrator needs `implementation_` addresses.

function getDeployerNonceAfterProtocolDeployment(uint256 deployerNonce_) public pure virtual returns (uint256) {
return deployerNonce_ + 2;
implementation_ = ContractHelper.getContractFrom(deployer_, deployerNonce_);
migrator_ = ContractHelper.getContractFrom(deployer_, deployerNonce_ + 1);
}
}
74 changes: 0 additions & 74 deletions script/DeployProduction.s.sol

This file was deleted.

Loading
Loading