Skip to content

Commit

Permalink
feat: Deploy Scripts (#75)
Browse files Browse the repository at this point in the history
  • Loading branch information
deluca-mike authored Aug 13, 2024
1 parent 55896c2 commit 5c1e17d
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 6 deletions.
11 changes: 7 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ profile ?=default
update:; forge update

# Deployment helpers
deploy-local :
FOUNDRY_PROFILE=production forge script script/Deploy.s.sol --rpc-url localhost --broadcast -v
deploy:
FOUNDRY_PROFILE=production forge script script/Deploy.s.sol --skip src --skip test --rpc-url mainnet --slow --broadcast -vvv --verify

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

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

# Run slither
slither :
Expand Down
57 changes: 57 additions & 0 deletions script/DeployBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.23;

import { ContractHelper } from "../lib/common/src/libs/ContractHelper.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.
*/
function deploy(
address mToken_,
address migrationAdmin_
) public virtual returns (address implementation_, address proxy_) {
// Wrapped M token needs `mToken_` and `migrationAdmin_` addresses.
// Proxy needs `implementation_` addresses.

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

function _getExpectedWrappedMTokenImplementation(
address deployer_,
uint256 deployerNonce_
) internal pure returns (address) {
return ContractHelper.getContractFrom(deployer_, deployerNonce_);
}

function getExpectedWrappedMTokenImplementation(
address deployer_,
uint256 deployerNonce_
) public pure virtual returns (address) {
return _getExpectedWrappedMTokenImplementation(deployer_, deployerNonce_);
}

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

function getExpectedWrappedMTokenProxy(
address deployer_,
uint256 deployerNonce_
) public pure virtual returns (address) {
return _getExpectedWrappedMTokenProxy(deployer_, deployerNonce_);
}

function getDeployerNonceAfterProtocolDeployment(uint256 deployerNonce_) public pure virtual returns (uint256) {
return deployerNonce_ + 2;
}
}
73 changes: 73 additions & 0 deletions script/DeployProduction.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.23;

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);

// NOTE: Ensure this is the correct M Token testnet/mainnet address.
address internal constant _M_TOKEN = 0x866A2BF4E572CbcF37D5071A7a58503Bfb36be1b;

// NOTE: Ensure this is the correct Migration Admin testnet/mainnet address.
address internal constant _MIGRATION_ADMIN = 0x431169728D75bd02f4053435b87D15c8d1FB2C72;

// NOTE: Ensure this is the correct deployer testnet/mainnet to use.
address internal constant _EXPECTED_DEPLOYER = 0xF2f1ACbe0BA726fEE8d75f3E32900526874740BB;

// NOTE: Ensure this is the correct nonce to use to deploy the Proxy on testnet/mainnet.
uint256 internal constant _DEPLOYER_PROXY_NONCE = 40;

// NOTE: Ensure this is the correct expected testnet/mainnet address for the Proxy.
address internal constant _EXPECTED_PROXY = 0x437cc33344a0B27A429f795ff6B469C72698B291;

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

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

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

uint64 currentNonce_ = vm.getNonce(deployer_);

if (currentNonce_ >= _DEPLOYER_PROXY_NONCE - 1) revert DeployerNonceTooHigh();

address expectedProxy_ = getExpectedWrappedMTokenProxy(deployer_, _DEPLOYER_PROXY_NONCE);

if (expectedProxy_ != _EXPECTED_PROXY) revert ExpectedProxyMismatch(_EXPECTED_PROXY, expectedProxy_);

vm.startBroadcast(deployer_);

// Burn nonces until to 1 before `_DEPLOYER_PROXY_NONCE` since implementation is deployed before proxy.
while (currentNonce_ < _DEPLOYER_PROXY_NONCE - 1) {
payable(deployer_).transfer(0);
++currentNonce_;
}

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

if (currentNonce_ != _DEPLOYER_PROXY_NONCE - 1) revert UnexpectedDeployerNonce();

(address implementation_, address proxy_) = deploy(_M_TOKEN, _MIGRATION_ADMIN);

vm.stopBroadcast();

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

if (proxy_ != _EXPECTED_PROXY) revert ResultingProxyMismatch(_EXPECTED_PROXY, proxy_);
}
}
1 change: 0 additions & 1 deletion src/WrappedMToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { Migratable } from "./Migratable.sol";

/*
██╗ ██╗██████╗ █████╗ ██████╗ ██████╗ ███████╗██████╗ ███╗ ███╗ ████████╗ ██████╗ ██╗ ██╗███████╗███╗ ██╗
██║ ██║██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗ ████╗ ████║ ╚══██╔══╝██╔═══██╗██║ ██╔╝██╔════╝████╗ ██║
██║ █╗ ██║██████╔╝███████║██████╔╝██████╔╝█████╗ ██║ ██║ ██╔████╔██║ ██║ ██║ ██║█████╔╝ █████╗ ██╔██╗ ██║
Expand Down
45 changes: 45 additions & 0 deletions test/integration/Deploy.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.23;

import { Test } from "../../lib/forge-std/src/Test.sol";

import { IWrappedMToken } from "../../src/interfaces/IWrappedMToken.sol";
import { IMTokenLike } from "../../src/interfaces/IMTokenLike.sol";
import { IRegistrarLike } from "../../src/interfaces/IRegistrarLike.sol";

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

contract Deploy is Test, DeployBase {
address internal constant _TTG_VAULT = 0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD;

address internal constant _M_TOKEN = 0x866A2BF4E572CbcF37D5071A7a58503Bfb36be1b;
address internal constant _MIGRATION_ADMIN = 0x431169728D75bd02f4053435b87D15c8d1FB2C72;
address internal constant _DEPLOYER = 0xF2f1ACbe0BA726fEE8d75f3E32900526874740BB;
uint256 internal constant _DEPLOYER_PROXY_NONCE = 40;
address internal constant _EXPECTED_PROXY = 0x437cc33344a0B27A429f795ff6B469C72698B291;

function test_deploy() external {
// Set nonce to 1 before `_DEPLOYER_PROXY_NONCE` since implementation is deployed before proxy.
vm.setNonce(_DEPLOYER, uint64(_DEPLOYER_PROXY_NONCE) - 1);

vm.startPrank(_DEPLOYER);
(address implementation_, address proxy_) = deploy(_M_TOKEN, _MIGRATION_ADMIN);
vm.stopPrank();

// Wrapped M Token Implementation assertions
assertEq(implementation_, getExpectedWrappedMTokenImplementation(_DEPLOYER, 39));
assertEq(IWrappedMToken(implementation_).migrationAdmin(), _MIGRATION_ADMIN);
assertEq(IWrappedMToken(implementation_).mToken(), _M_TOKEN);
assertEq(IWrappedMToken(implementation_).registrar(), IMTokenLike(_M_TOKEN).ttgRegistrar());
assertEq(IWrappedMToken(implementation_).vault(), IRegistrarLike(IMTokenLike(_M_TOKEN).ttgRegistrar()).vault());

// // Wrapped M Token Proxy assertions
assertEq(proxy_, getExpectedWrappedMTokenProxy(_DEPLOYER, 39));
assertEq(proxy_, _EXPECTED_PROXY);
assertEq(IWrappedMToken(proxy_).migrationAdmin(), _MIGRATION_ADMIN);
assertEq(IWrappedMToken(proxy_).mToken(), _M_TOKEN);
assertEq(IWrappedMToken(proxy_).registrar(), IMTokenLike(_M_TOKEN).ttgRegistrar());
assertEq(IWrappedMToken(proxy_).vault(), IRegistrarLike(IMTokenLike(_M_TOKEN).ttgRegistrar()).vault());
}
}
2 changes: 1 addition & 1 deletion test/integration/Protocol.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ contract ProtocolIntegrationTests is TestBase {
}

function testFuzz_full(uint256 seed_) external {
vm.skip(false);
vm.skip(true);

for (uint256 index_; index_ < _accounts.length; ++index_) {
_giveM(_accounts[index_], 100_000e6);
Expand Down

0 comments on commit 5c1e17d

Please sign in to comment.