Skip to content
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
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