Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
4 changes: 2 additions & 2 deletions protocol-units/settlement/mcr/contracts/foundry.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[profile.default]
via_ir = true
optimizer = true
src = "src"
out = "out"
libs = ["lib"]
ffi = true
gas_limit = 9223372036854775807 # this is only needed for the multiround settlement test
build_info = true
extra_output = ["storageLayout"]
optimizer = true
optimizer_runs = 200

solc = "0.8.26"
evm_version = "cancun"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
pragma solidity ^0.8.13;

import "forge-std/Script.sol";
import {MOVEToken} from "../src/token/MOVEToken.sol";
import { Helper } from "./helpers/Helper.sol";
import { MCRDeployer } from "./MCRDeployer.s.sol";
import { MovementStakingDeployer } from "./MovementStakingDeployer.s.sol";
import { StlMoveDeployer } from "./StlMoveDeployer.s.sol";
import { MOVETokenDeployer } from "./MOVETokenDeployer.s.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";

contract CoreDeployer is MCRDeployer, MovementStakingDeployer, StlMoveDeployer, MOVETokenDeployer {

function run() external override(MCRDeployer, MovementStakingDeployer, StlMoveDeployer, MOVETokenDeployer) {

// load config and deployments data
_loadExternalData();

uint256 signer = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(signer);

// Deploy CREATE3Factory, Safes and Timelock if not deployed
_deployDependencies();

// Deploy or upgrade contracts conditionally
deployment.moveAdmin == ZERO && deployment.move == ZERO ?
_deployMove() : deployment.moveAdmin != ZERO && deployment.move != ZERO ?
// if move is already deployed, upgrade it
_upgradeMove() : revert("MOVE: both admin and proxy should be registered");

// requires move to be deployed
deployment.stakingAdmin == ZERO && deployment.staking == ZERO && deployment.move != ZERO ?
_deployStaking() : deployment.stakingAdmin != ZERO && deployment.staking != ZERO ?
// if staking is already deployed, upgrade it
_upgradeStaking() : revert("STAKING: both admin and proxy should be registered");

// requires move to be deployed
deployment.stlMoveAdmin == ZERO && deployment.stlMove == ZERO && deployment.move != ZERO ?
_deployStlMove() : deployment.stlMoveAdmin != ZERO && deployment.stlMove != ZERO ?
// if stlMove is already deployed, upgrade it
_upgradeStlMove() : revert("STL: both admin and proxy should be registered");

// requires staking and move to be deployed
deployment.mcrAdmin == ZERO && deployment.mcr == ZERO && deployment.move != ZERO && deployment.staking != ZERO ?
_deployMCR() : deployment.mcrAdmin != ZERO && deployment.mcr != ZERO ?
// if mcr is already deployed, upgrade it
_upgradeMCR() : revert("MCR: both admin and proxy should be registered");

// Only write to file if chainid is not running a foundry local chain and if broadcasting
if (block.chainid == foundryChainId) {
_allowSameContract();
_upgradeMove();
_upgradeStaking();
_upgradeStlMove();
_upgradeMCR();
} else {
if (vm.isContext(VmSafe.ForgeContext.ScriptBroadcast)) {
_writeDeployments();
}
}

vm.stopBroadcast();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pragma solidity ^0.8.19;

import "forge-std/Script.sol";
import "../src/token/MOVETokenDev.sol";
import {IMintableToken, MintableToken} from "../src/token/base/MintableToken.sol";
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {Helper} from "./helpers/Helper.sol";

contract DeployMOVETokenDev is Helper {
address public manager = 0x5A368EDEbF574162B84f8ECFE48e9De4f520E087;
uint256 public signer = vm.envUint("TEST_1");
function run() external {
vm.startBroadcast(signer);

MOVETokenDev moveTokenImplementation = new MOVETokenDev();
TransparentUpgradeableProxy moveTokenProxy = new TransparentUpgradeableProxy(
address(moveTokenImplementation),
manager,
abi.encodeWithSignature("initialize(address)", manager)
);

console.log("Move Token Proxy: %s", address(moveTokenProxy));

vm.stopBroadcast();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
pragma solidity ^0.8.13;

import "forge-std/Script.sol";
import {MCR} from "../src/settlement/MCR.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
import { Helper } from "./helpers/Helper.sol";

contract MCRDeployer is Helper {

function run() external virtual {

// load config and deployments data
_loadExternalData();

uint256 signer = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(signer);

// Deploy CREATE3Factory, Safes and Timelock if not deployed
_deployDependencies();

deployment.mcrAdmin == ZERO && deployment.mcr == ZERO && deployment.move != ZERO && deployment.staking != ZERO ?
_deployMCR() : deployment.mcrAdmin != ZERO && deployment.mcr != ZERO ?
_upgradeMCR() : revert("MCR: both admin and proxy should be registered");

vm.stopBroadcast();

// Only write to file if chainid is not running a foundry local chain
if (vm.isContext(VmSafe.ForgeContext.ScriptBroadcast)) {
_writeDeployments();
}
}

// •☽────✧˖°˖DANGER ZONE˖°˖✧────☾•
// Modifications to the following functions have to be throughly tested

function _deployMCR() internal {
console.log("MCR: deploying");
MCR mcrImplementation = new MCR();
vm.recordLogs();
mcrProxy = new TransparentUpgradeableProxy(
address(mcrImplementation),
address(timelock),
abi.encodeWithSignature(
mcrSignature,
address(stakingProxy),
128,
100 ether,
100 ether,
config.signersLabs
)
);
console.log("MCR deployment records:");
console.log("proxy", address(mcrProxy));
deployment.mcr = address(mcrProxy);
deployment.mcrAdmin = _storeAdminDeployment();
}

function _upgradeMCR() internal {
console.log("MCR: upgrading");
MCR newMCRImplementation = new MCR();
_checkBytecodeDifference(address(newMCRImplementation), deployment.mcr);
bytes memory data = abi.encodeWithSignature(
"schedule(address,uint256,bytes,bytes32,bytes32,uint256)",
address(deployment.mcrAdmin),
0,
abi.encodeWithSignature(
"upgradeAndCall(address,address,bytes)",
address(mcrProxy),
address(newMCRImplementation),
""
),
bytes32(0),
bytes32(0),
config.minDelay
);
_proposeUpgrade(data, "mcr.json");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
pragma solidity ^0.8.13;

import "forge-std/Script.sol";
import {MOVEToken} from "../src/token/MOVEToken.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import { Helper, ProxyAdmin } from "./helpers/Helper.sol";
import {ICREATE3Factory} from "./helpers/Create3/ICREATE3Factory.sol";

// Script intended to be used for deploying the MOVE token from an EOA
// Utilizies existing safes and sets them as proposers and executors.
// The MOVEToken contract takes in the Movement Foundation address and sets it as its own admin for future upgrades.
// The whole supply is minted to the Movement Foundation Safe.
// The script also verifies that the token has the correct balances, decimals and permissions.
contract MOVETokenDeployer is Helper {
// COMMANDS
// mainnet
// forge script MOVETokenDeployer --fork-url https://eth.llamarpc.com --verify --etherscan-api-key ETHERSCAN_API_KEY
// testnet
// forge script MOVETokenDeployer --fork-url https://eth-sepolia.api.onfinality.io/public
// Safes should be already deployed
bytes32 public salt = 0x0;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

function run() external virtual {

// load config and deployments data
_loadExternalData();

uint256 signer = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(signer);

// Deploy CREATE3Factory, Safes and Timelock if not deployed
_deployDependencies();

deployment.moveAdmin == ZERO && deployment.move == ZERO ?
_deployMove() : deployment.moveAdmin != ZERO && deployment.move != ZERO ?
// if move is already deployed, upgrade it
_upgradeMove() : revert("MOVE: both admin and proxy should be registered");

require(MOVEToken(deployment.move).balanceOf(address(deployment.movementAnchorage)) == 999999998000000000, "Movement Anchorage Safe balance is wrong");
require(MOVEToken(deployment.move).decimals() == 8, "Decimals are expected to be 8");
require(MOVEToken(deployment.move).totalSupply() == 1000000000000000000,"Total supply is wrong");
require(MOVEToken(deployment.move).hasRole(DEFAULT_ADMIN_ROLE, address(deployment.movementFoundationSafe)),"Movement Foundation expected to have token admin role");
require(!MOVEToken(deployment.move).hasRole(DEFAULT_ADMIN_ROLE, address(deployment.movementLabsSafe)),"Movement Labs not expected to have token admin role");
require(!MOVEToken(deployment.move).hasRole(DEFAULT_ADMIN_ROLE, address(timelock)),"Timelock not expected to have token admin role");
vm.stopBroadcast();

if (vm.isContext(VmSafe.ForgeContext.ScriptBroadcast)) {
_writeDeployments();
}
}

// •☽────✧˖°˖DANGER ZONE˖°˖✧────☾•
// Modifications to the following functions have to be throughly tested

function _deployMove() internal {
console.log("MOVE: deploying");
MOVEToken moveImplementation = new MOVEToken();
// genetares bytecode for CREATE3 deployment
bytes memory bytecode = abi.encodePacked(
type(TransparentUpgradeableProxy).creationCode,
abi.encode(address(moveImplementation), address(timelock), abi.encodeWithSignature(moveSignature, deployment.movementFoundationSafe, deployment.movementAnchorage))
);
vm.recordLogs();
// deploys the MOVE token proxy using CREATE3
moveProxy = TransparentUpgradeableProxy(payable(ICREATE3Factory(create3).deploy(salt, bytecode)));
console.log("MOVEToken deployment records:");
console.log("proxy", address(moveProxy));
deployment.move = address(moveProxy);
deployment.moveAdmin = _storeAdminDeployment();
}

function _upgradeMove() internal {
console.log("MOVE: upgrading");
MOVEToken newMoveImplementation = new MOVEToken();
_checkBytecodeDifference(address(newMoveImplementation), deployment.move);
// Prepare the data for the upgrade
bytes memory data = abi.encodeWithSignature(
"schedule(address,uint256,bytes,bytes32,bytes32,uint256)",
address(deployment.moveAdmin),
0,
abi.encodeWithSignature(
"upgradeAndCall(address,address,bytes)",
address(deployment.move),
address(newMoveImplementation),
""
),
bytes32(0),
bytes32(0),
config.minDelay
);

_proposeUpgrade(data, "movetoken.json");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
pragma solidity ^0.8.13;

import "forge-std/Script.sol";
import {MovementStaking} from "../src/staking/MovementStaking.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
import { Helper } from "./helpers/Helper.sol";

contract MovementStakingDeployer is Helper {

function run() external virtual {

// load config and deployments data
_loadExternalData();

uint256 signer = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(signer);

// Deploy CREATE3Factory, Safes and Timelock if not deployed
_deployDependencies();

deployment.stakingAdmin == ZERO && deployment.staking == ZERO && deployment.move != ZERO ?
_deployStaking() : deployment.stakingAdmin != ZERO && deployment.staking != ZERO ?
_upgradeStaking() : revert("STAKING: both admin and proxy should be registered");

vm.stopBroadcast();

// Only write to file if chainid is not running a foundry local chain
if (vm.isContext(VmSafe.ForgeContext.ScriptBroadcast)) {
_writeDeployments();
}
}

// •☽────✧˖°˖DANGER ZONE˖°˖✧────☾•
// Modifications to the following functions have to be throughly tested

function _deployStaking() internal {
console.log("STAKING: deploying");
MovementStaking stakingImplementation = new MovementStaking();
vm.recordLogs();
stakingProxy = new TransparentUpgradeableProxy(
address(stakingImplementation),
address(timelock),
abi.encodeWithSignature(stakingSignature, address(moveProxy))
);
console.log("STAKING deployment records:");
console.log("proxy", address(stakingProxy));
deployment.staking = address(stakingProxy);
deployment.stakingAdmin = _storeAdminDeployment();
}

function _upgradeStaking() internal {
Comment thread
Primata marked this conversation as resolved.
console.log("STAKING: upgrading");
MovementStaking newStakingImplementation = new MovementStaking();
_checkBytecodeDifference(address(newStakingImplementation), deployment.staking);
// Prepare the data for the upgrade
bytes memory data = abi.encodeWithSignature(
"schedule(address,uint256,bytes,bytes32,bytes32,uint256)",
address(deployment.stakingAdmin),
0,
abi.encodeWithSignature(
"upgradeAndCall(address,address,bytes)",
address(stakingProxy),
address(newStakingImplementation),
""
),
bytes32(0),
bytes32(0),
config.minDelay
);

_proposeUpgrade(data, "staking.json");
}


}
Loading
Loading