Skip to content

Commit

Permalink
feat: post-deploy v2 prep
Browse files Browse the repository at this point in the history
- solc 0.8.26
- latest common
- latest forge-std
- registrar as constructor arg
- excess destination as constructor arg
- constants made public
- token name changed
- batch start and stop earning
- IsApprovedEarner and NotApprovedEarner errors have account as parameter
- Indexing Math no longer needed?
- Basic Migrator contract introduced
- version bump
- use more from common
- zero account checks

feat: post-deploy v2 prep

- solc 0.8.26
- latest common
- latest forge-std
- registrar as constructor arg
- excess destination as constructor arg
- constants made public
- token name changed
- `IsApprovedEarner` and `NotApprovedEarner` errors have account as parameter
- basic Migrator contract introduced
- version bump
- use more from common
- more test coverage
- fixed scripts to allow for generic deploy and mainnet upgrade
  • Loading branch information
deluca-mike committed Jan 17, 2025
1 parent 050d781 commit d25d55a
Show file tree
Hide file tree
Showing 41 changed files with 1,896 additions and 1,929 deletions.
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 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 MAINNET_RPC_URL=$(DEPLOY_RPC_URL) forge script script/Deploy.s.sol --skip src --skip test --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("Migrator 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

0 comments on commit d25d55a

Please sign in to comment.