Skip to content

Commit d224a0a

Browse files
PrimataCopilot
andauthored
feat: improve contract pipeline
Co-authored-by: Copilot <[email protected]>
1 parent 5e606c9 commit d224a0a

25 files changed

+3126
-5
lines changed

protocol-units/settlement/mcr/contracts/foundry.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
[profile.default]
2-
via_ir = true
3-
optimizer = true
42
src = "src"
53
out = "out"
64
libs = ["lib"]
75
ffi = true
86
gas_limit = 9223372036854775807 # this is only needed for the multiround settlement test
97
build_info = true
108
extra_output = ["storageLayout"]
9+
optimizer = true
10+
optimizer_runs = 200
1111

1212
solc = "0.8.26"
1313
evm_version = "cancun"
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
pragma solidity ^0.8.13;
2+
3+
import "forge-std/Script.sol";
4+
import {MOVEToken} from "../src/token/MOVEToken.sol";
5+
import { Helper } from "./helpers/Helper.sol";
6+
import { MCRDeployer } from "./MCRDeployer.s.sol";
7+
import { MovementStakingDeployer } from "./MovementStakingDeployer.s.sol";
8+
import { StlMoveDeployer } from "./StlMoveDeployer.s.sol";
9+
import { MOVETokenDeployer } from "./MOVETokenDeployer.s.sol";
10+
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
11+
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
12+
13+
contract CoreDeployer is MCRDeployer, MovementStakingDeployer, StlMoveDeployer, MOVETokenDeployer {
14+
15+
function run() external override(MCRDeployer, MovementStakingDeployer, StlMoveDeployer, MOVETokenDeployer) {
16+
17+
// load config and deployments data
18+
_loadExternalData();
19+
20+
uint256 signer = vm.envUint("PRIVATE_KEY");
21+
vm.startBroadcast(signer);
22+
23+
// Deploy CREATE3Factory, Safes and Timelock if not deployed
24+
_deployDependencies();
25+
26+
// Deploy or upgrade contracts conditionally
27+
deployment.moveAdmin == ZERO && deployment.move == ZERO ?
28+
_deployMove() : deployment.moveAdmin != ZERO && deployment.move != ZERO ?
29+
// if move is already deployed, upgrade it
30+
_upgradeMove() : revert("MOVE: both admin and proxy should be registered");
31+
32+
// requires move to be deployed
33+
deployment.stakingAdmin == ZERO && deployment.staking == ZERO && deployment.move != ZERO ?
34+
_deployStaking() : deployment.stakingAdmin != ZERO && deployment.staking != ZERO ?
35+
// if staking is already deployed, upgrade it
36+
_upgradeStaking() : revert("STAKING: both admin and proxy should be registered");
37+
38+
// requires move to be deployed
39+
deployment.stlMoveAdmin == ZERO && deployment.stlMove == ZERO && deployment.move != ZERO ?
40+
_deployStlMove() : deployment.stlMoveAdmin != ZERO && deployment.stlMove != ZERO ?
41+
// if stlMove is already deployed, upgrade it
42+
_upgradeStlMove() : revert("STL: both admin and proxy should be registered");
43+
44+
// requires staking and move to be deployed
45+
deployment.mcrAdmin == ZERO && deployment.mcr == ZERO && deployment.move != ZERO && deployment.staking != ZERO ?
46+
_deployMCR() : deployment.mcrAdmin != ZERO && deployment.mcr != ZERO ?
47+
// if mcr is already deployed, upgrade it
48+
_upgradeMCR() : revert("MCR: both admin and proxy should be registered");
49+
50+
// Only write to file if chainid is not running a foundry local chain and if broadcasting
51+
if (block.chainid == foundryChainId) {
52+
_allowSameContract();
53+
_upgradeMove();
54+
_upgradeStaking();
55+
_upgradeStlMove();
56+
_upgradeMCR();
57+
} else {
58+
if (vm.isContext(VmSafe.ForgeContext.ScriptBroadcast)) {
59+
_writeDeployments();
60+
}
61+
}
62+
63+
vm.stopBroadcast();
64+
}
65+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
pragma solidity ^0.8.19;
2+
3+
import "forge-std/Script.sol";
4+
import "../src/token/MOVETokenDev.sol";
5+
import {IMintableToken, MintableToken} from "../src/token/base/MintableToken.sol";
6+
import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
7+
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
8+
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
9+
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
10+
import {Helper} from "./helpers/Helper.sol";
11+
12+
contract DeployMOVETokenDev is Helper {
13+
address public manager = 0x5A368EDEbF574162B84f8ECFE48e9De4f520E087;
14+
uint256 public signer = vm.envUint("TEST_1");
15+
function run() external {
16+
vm.startBroadcast(signer);
17+
18+
MOVETokenDev moveTokenImplementation = new MOVETokenDev();
19+
TransparentUpgradeableProxy moveTokenProxy = new TransparentUpgradeableProxy(
20+
address(moveTokenImplementation),
21+
manager,
22+
abi.encodeWithSignature("initialize(address)", manager)
23+
);
24+
25+
console.log("Move Token Proxy: %s", address(moveTokenProxy));
26+
27+
vm.stopBroadcast();
28+
}
29+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
pragma solidity ^0.8.13;
2+
3+
import "forge-std/Script.sol";
4+
import {MCR} from "../src/settlement/MCR.sol";
5+
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
6+
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
7+
import { Helper } from "./helpers/Helper.sol";
8+
9+
contract MCRDeployer is Helper {
10+
11+
function run() external virtual {
12+
13+
// load config and deployments data
14+
_loadExternalData();
15+
16+
uint256 signer = vm.envUint("PRIVATE_KEY");
17+
vm.startBroadcast(signer);
18+
19+
// Deploy CREATE3Factory, Safes and Timelock if not deployed
20+
_deployDependencies();
21+
22+
deployment.mcrAdmin == ZERO && deployment.mcr == ZERO && deployment.move != ZERO && deployment.staking != ZERO ?
23+
_deployMCR() : deployment.mcrAdmin != ZERO && deployment.mcr != ZERO ?
24+
_upgradeMCR() : revert("MCR: both admin and proxy should be registered");
25+
26+
vm.stopBroadcast();
27+
28+
// Only write to file if chainid is not running a foundry local chain
29+
if (vm.isContext(VmSafe.ForgeContext.ScriptBroadcast)) {
30+
_writeDeployments();
31+
}
32+
}
33+
34+
// •☽────✧˖°˖DANGER ZONE˖°˖✧────☾•
35+
// Modifications to the following functions have to be throughly tested
36+
37+
function _deployMCR() internal {
38+
console.log("MCR: deploying");
39+
MCR mcrImplementation = new MCR();
40+
vm.recordLogs();
41+
mcrProxy = new TransparentUpgradeableProxy(
42+
address(mcrImplementation),
43+
address(timelock),
44+
abi.encodeWithSignature(
45+
mcrSignature,
46+
address(stakingProxy),
47+
128,
48+
100 ether,
49+
100 ether,
50+
config.signersLabs
51+
)
52+
);
53+
console.log("MCR deployment records:");
54+
console.log("proxy", address(mcrProxy));
55+
deployment.mcr = address(mcrProxy);
56+
deployment.mcrAdmin = _storeAdminDeployment();
57+
}
58+
59+
function _upgradeMCR() internal {
60+
console.log("MCR: upgrading");
61+
MCR newMCRImplementation = new MCR();
62+
_checkBytecodeDifference(address(newMCRImplementation), deployment.mcr);
63+
bytes memory data = abi.encodeWithSignature(
64+
"schedule(address,uint256,bytes,bytes32,bytes32,uint256)",
65+
address(deployment.mcrAdmin),
66+
0,
67+
abi.encodeWithSignature(
68+
"upgradeAndCall(address,address,bytes)",
69+
address(mcrProxy),
70+
address(newMCRImplementation),
71+
""
72+
),
73+
bytes32(0),
74+
bytes32(0),
75+
config.minDelay
76+
);
77+
_proposeUpgrade(data, "mcr.json");
78+
}
79+
80+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
pragma solidity ^0.8.13;
2+
3+
import "forge-std/Script.sol";
4+
import {MOVEToken} from "../src/token/MOVEToken.sol";
5+
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
6+
import { Helper, ProxyAdmin } from "./helpers/Helper.sol";
7+
import {ICREATE3Factory} from "./helpers/Create3/ICREATE3Factory.sol";
8+
9+
// Script intended to be used for deploying the MOVE token from an EOA
10+
// Utilizies existing safes and sets them as proposers and executors.
11+
// The MOVEToken contract takes in the Movement Foundation address and sets it as its own admin for future upgrades.
12+
// The whole supply is minted to the Movement Foundation Safe.
13+
// The script also verifies that the token has the correct balances, decimals and permissions.
14+
contract MOVETokenDeployer is Helper {
15+
// COMMANDS
16+
// mainnet
17+
// forge script MOVETokenDeployer --fork-url https://eth.llamarpc.com --verify --etherscan-api-key ETHERSCAN_API_KEY
18+
// testnet
19+
// forge script MOVETokenDeployer --fork-url https://eth-sepolia.api.onfinality.io/public
20+
// Safes should be already deployed
21+
bytes32 public salt = 0x0;
22+
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
23+
24+
function run() external virtual {
25+
26+
// load config and deployments data
27+
_loadExternalData();
28+
29+
uint256 signer = vm.envUint("PRIVATE_KEY");
30+
vm.startBroadcast(signer);
31+
32+
// Deploy CREATE3Factory, Safes and Timelock if not deployed
33+
_deployDependencies();
34+
35+
deployment.moveAdmin == ZERO && deployment.move == ZERO ?
36+
_deployMove() : deployment.moveAdmin != ZERO && deployment.move != ZERO ?
37+
// if move is already deployed, upgrade it
38+
_upgradeMove() : revert("MOVE: both admin and proxy should be registered");
39+
40+
require(MOVEToken(deployment.move).balanceOf(address(deployment.movementAnchorage)) == 999999998000000000, "Movement Anchorage Safe balance is wrong");
41+
require(MOVEToken(deployment.move).decimals() == 8, "Decimals are expected to be 8");
42+
require(MOVEToken(deployment.move).totalSupply() == 1000000000000000000,"Total supply is wrong");
43+
require(MOVEToken(deployment.move).hasRole(DEFAULT_ADMIN_ROLE, address(deployment.movementFoundationSafe)),"Movement Foundation expected to have token admin role");
44+
require(!MOVEToken(deployment.move).hasRole(DEFAULT_ADMIN_ROLE, address(deployment.movementLabsSafe)),"Movement Labs not expected to have token admin role");
45+
require(!MOVEToken(deployment.move).hasRole(DEFAULT_ADMIN_ROLE, address(timelock)),"Timelock not expected to have token admin role");
46+
vm.stopBroadcast();
47+
48+
if (vm.isContext(VmSafe.ForgeContext.ScriptBroadcast)) {
49+
_writeDeployments();
50+
}
51+
}
52+
53+
// •☽────✧˖°˖DANGER ZONE˖°˖✧────☾•
54+
// Modifications to the following functions have to be throughly tested
55+
56+
function _deployMove() internal {
57+
console.log("MOVE: deploying");
58+
MOVEToken moveImplementation = new MOVEToken();
59+
// genetares bytecode for CREATE3 deployment
60+
bytes memory bytecode = abi.encodePacked(
61+
type(TransparentUpgradeableProxy).creationCode,
62+
abi.encode(address(moveImplementation), address(timelock), abi.encodeWithSignature(moveSignature, deployment.movementFoundationSafe, deployment.movementAnchorage))
63+
);
64+
vm.recordLogs();
65+
// deploys the MOVE token proxy using CREATE3
66+
moveProxy = TransparentUpgradeableProxy(payable(ICREATE3Factory(create3).deploy(salt, bytecode)));
67+
console.log("MOVEToken deployment records:");
68+
console.log("proxy", address(moveProxy));
69+
deployment.move = address(moveProxy);
70+
deployment.moveAdmin = _storeAdminDeployment();
71+
}
72+
73+
function _upgradeMove() internal {
74+
console.log("MOVE: upgrading");
75+
MOVEToken newMoveImplementation = new MOVEToken();
76+
_checkBytecodeDifference(address(newMoveImplementation), deployment.move);
77+
// Prepare the data for the upgrade
78+
bytes memory data = abi.encodeWithSignature(
79+
"schedule(address,uint256,bytes,bytes32,bytes32,uint256)",
80+
address(deployment.moveAdmin),
81+
0,
82+
abi.encodeWithSignature(
83+
"upgradeAndCall(address,address,bytes)",
84+
address(deployment.move),
85+
address(newMoveImplementation),
86+
""
87+
),
88+
bytes32(0),
89+
bytes32(0),
90+
config.minDelay
91+
);
92+
93+
_proposeUpgrade(data, "movetoken.json");
94+
}
95+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
pragma solidity ^0.8.13;
2+
3+
import "forge-std/Script.sol";
4+
import {MovementStaking} from "../src/staking/MovementStaking.sol";
5+
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
6+
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
7+
import { Helper } from "./helpers/Helper.sol";
8+
9+
contract MovementStakingDeployer is Helper {
10+
11+
function run() external virtual {
12+
13+
// load config and deployments data
14+
_loadExternalData();
15+
16+
uint256 signer = vm.envUint("PRIVATE_KEY");
17+
vm.startBroadcast(signer);
18+
19+
// Deploy CREATE3Factory, Safes and Timelock if not deployed
20+
_deployDependencies();
21+
22+
deployment.stakingAdmin == ZERO && deployment.staking == ZERO && deployment.move != ZERO ?
23+
_deployStaking() : deployment.stakingAdmin != ZERO && deployment.staking != ZERO ?
24+
_upgradeStaking() : revert("STAKING: both admin and proxy should be registered");
25+
26+
vm.stopBroadcast();
27+
28+
// Only write to file if chainid is not running a foundry local chain
29+
if (vm.isContext(VmSafe.ForgeContext.ScriptBroadcast)) {
30+
_writeDeployments();
31+
}
32+
}
33+
34+
// •☽────✧˖°˖DANGER ZONE˖°˖✧────☾•
35+
// Modifications to the following functions have to be throughly tested
36+
37+
function _deployStaking() internal {
38+
console.log("STAKING: deploying");
39+
MovementStaking stakingImplementation = new MovementStaking();
40+
vm.recordLogs();
41+
stakingProxy = new TransparentUpgradeableProxy(
42+
address(stakingImplementation),
43+
address(timelock),
44+
abi.encodeWithSignature(stakingSignature, address(moveProxy))
45+
);
46+
console.log("STAKING deployment records:");
47+
console.log("proxy", address(stakingProxy));
48+
deployment.staking = address(stakingProxy);
49+
deployment.stakingAdmin = _storeAdminDeployment();
50+
}
51+
52+
function _upgradeStaking() internal {
53+
console.log("STAKING: upgrading");
54+
MovementStaking newStakingImplementation = new MovementStaking();
55+
_checkBytecodeDifference(address(newStakingImplementation), deployment.staking);
56+
// Prepare the data for the upgrade
57+
bytes memory data = abi.encodeWithSignature(
58+
"schedule(address,uint256,bytes,bytes32,bytes32,uint256)",
59+
address(deployment.stakingAdmin),
60+
0,
61+
abi.encodeWithSignature(
62+
"upgradeAndCall(address,address,bytes)",
63+
address(stakingProxy),
64+
address(newStakingImplementation),
65+
""
66+
),
67+
bytes32(0),
68+
bytes32(0),
69+
config.minDelay
70+
);
71+
72+
_proposeUpgrade(data, "staking.json");
73+
}
74+
75+
76+
}

0 commit comments

Comments
 (0)