diff --git a/audits/ChainSecurity_MakerDAO_EndGame_Toolkit_contracts_audit.pdf b/audits/ChainSecurity_MakerDAO_EndGame_Toolkit_contracts_audit.pdf new file mode 100644 index 0000000..758e285 Binary files /dev/null and b/audits/ChainSecurity_MakerDAO_EndGame_Toolkit_contracts_audit.pdf differ diff --git a/audits/ChainSecurity_MakerDAO_Endgame_Toolkit_audit.pdf b/audits/ChainSecurity_MakerDAO_Endgame_Toolkit_scripts_audit.pdf similarity index 93% rename from audits/ChainSecurity_MakerDAO_Endgame_Toolkit_audit.pdf rename to audits/ChainSecurity_MakerDAO_Endgame_Toolkit_scripts_audit.pdf index 29de345..0cf3b82 100644 Binary files a/audits/ChainSecurity_MakerDAO_Endgame_Toolkit_audit.pdf and b/audits/ChainSecurity_MakerDAO_Endgame_Toolkit_scripts_audit.pdf differ diff --git a/foundry.toml b/foundry.toml index 974e852..70ab1dd 100644 --- a/foundry.toml +++ b/foundry.toml @@ -5,6 +5,7 @@ script = 'script' libs = ['lib'] solc_version = '0.8.16' optimizer = true +optimizer_runs = 200 unchecked_cheatcode_artifacts = true fs_permissions = [ { access = "read", path = "./out/" }, @@ -28,7 +29,8 @@ script = 'script-0_6_x' # you can install it with the default profile. libs = ['lib-0_6_x', 'lib'] solc_version = '0.6.12' -optimizer = false +optimizer = true +optimizer_runs = 200 unchecked_cheatcode_artifacts = true fs_permissions = [ { access = "read", path = "./out/" }, diff --git a/script/dependencies/VestInit.sol b/script/dependencies/VestInit.sol index 0a5b0ae..4e8a216 100644 --- a/script/dependencies/VestInit.sol +++ b/script/dependencies/VestInit.sol @@ -15,10 +15,6 @@ pragma solidity ^0.8.16; -struct VestInitParams { - uint256 cap; -} - struct VestCreateParams { address usr; uint256 tot; @@ -27,11 +23,8 @@ struct VestCreateParams { uint256 eta; } +/// @dev Handles vesting stream creation. Assumes `DssVest` parameters are initialized somewhere else. library VestInit { - function init(address vest, VestInitParams memory p) internal { - DssVestLike(vest).file("cap", p.cap); - } - function create(address vest, VestCreateParams memory p) internal returns (uint256 vestId) { vestId = DssVestLike(vest).create( p.usr, @@ -47,8 +40,6 @@ library VestInit { } interface DssVestLike { - function file(bytes32 _what, uint256 _data) external; - function create( address _usr, uint256 _tot, diff --git a/script/dependencies/phase-1b/Usds01PreFarmingInit.sol b/script/dependencies/phase-1b/Usds01PreFarmingInit.sol index 7b1a6ce..8a2e3d3 100644 --- a/script/dependencies/phase-1b/Usds01PreFarmingInit.sol +++ b/script/dependencies/phase-1b/Usds01PreFarmingInit.sol @@ -33,9 +33,10 @@ library Usds01PreFarmingInit { StakingRewardsLike(p.rewards).rewardsToken() == address(0), "Usds01PreFarmingInit/invalid-rewards-token" ); + require(StakingRewardsLike(p.rewards).rewardRate() == 0, "Usds01PreFarmingInit/reward-rate-not-zero"); require( - StakingRewardsLike(p.rewards).lastUpdateTime() == 0, - "Usds01PreFarmingInit/rewards-last-update-time-invalid" + StakingRewardsLike(p.rewards).rewardsDistribution() == address(0), + "Usds01PreFarmingInit/rewards-distribution-already-set" ); require( StakingRewardsLike(p.rewards).owner() == chainlog.getAddress("MCD_PAUSE_PROXY"), @@ -47,10 +48,12 @@ library Usds01PreFarmingInit { } interface StakingRewardsLike { - function lastUpdateTime() external view returns (uint256); - function owner() external view returns (address); + function rewardRate() external view returns (uint256); + + function rewardsDistribution() external view returns (address); + function rewardsToken() external view returns (address); function stakingToken() external view returns (address); diff --git a/script/dependencies/phase-1b/UsdsSkyFarmingInit.sol b/script/dependencies/phase-1b/UsdsSkyFarmingInit.sol index fdf7f7b..591c052 100644 --- a/script/dependencies/phase-1b/UsdsSkyFarmingInit.sol +++ b/script/dependencies/phase-1b/UsdsSkyFarmingInit.sol @@ -40,18 +40,24 @@ library UsdsSkyFarmingInit { ChainlogLike internal constant chainlog = ChainlogLike(0xdA0Ab1e0017DEbCd72Be8599041a2aa3bA7e740F); function init(UsdsSkyFarmingInitParams memory p) internal returns (UsdsSkyFarmingInitResult memory r) { - address stakingToken = StakingRewardsLike(p.rewards).stakingToken(); - address rewardsToken = StakingRewardsLike(p.rewards).rewardsToken(); - - require(stakingToken != rewardsToken, "UsdsSkyFarmingInit/rewards-token-same-as-staking-token"); - require(DssVestWithGemLike(p.vest).gem() == p.sky, "UsdsSkyFarmingInit/vest-gem-mismatch"); - require(stakingToken == p.usds, "UsdsSkyFarmingInit/rewards-staking-token-mismatch"); - require(rewardsToken == p.sky, "UsdsSkyFarmingInit/rewards-rewards-token-mismatch"); require( - StakingRewardsLike(p.rewards).lastUpdateTime() == 0, - "UsdsSkyFarmingInit/rewards-last-update-time-invalid" + StakingRewardsLike(p.rewards).stakingToken() == p.usds, + "UsdsSkyFarmingInit/rewards-staking-token-mismatch" + ); + require( + StakingRewardsLike(p.rewards).rewardsToken() == p.sky, + "UsdsSkyFarmingInit/rewards-rewards-token-mismatch" + ); + require(StakingRewardsLike(p.rewards).rewardRate() == 0, "UsdsSkyFarmingInit/reward-rate-not-zero"); + require( + StakingRewardsLike(p.rewards).rewardsDistribution() == address(0), + "UsdsSkyFarmingInit/rewards-distribution-already-set" + ); + require( + StakingRewardsLike(p.rewards).owner() == chainlog.getAddress("MCD_PAUSE_PROXY"), + "UsdsSkyFarmingInit/invalid-owner" ); require(VestedRewardsDistributionLike(p.dist).gem() == p.sky, "UsdsSkyFarmingInit/dist-gem-mismatch"); @@ -64,7 +70,6 @@ library UsdsSkyFarmingInit { // `vest` is expected to be an instance of `DssVestMintable`. // Check if minting rights on `sky` were granted to `vest`. require(WardsLike(p.sky).wards(p.vest) == 1, "UsdsSkyFarmingInit/missing-sky-rely-vest"); - // Set `dist` with `rewardsDistribution` role in `rewards`. StakingRewardsInit.init(p.rewards, StakingRewardsInitParams({dist: p.dist})); @@ -93,7 +98,11 @@ interface DssVestWithGemLike { } interface StakingRewardsLike { - function lastUpdateTime() external view returns (uint256); + function owner() external view returns (address); + + function rewardRate() external view returns (uint256); + + function rewardsDistribution() external view returns (address); function rewardsToken() external view returns (address); @@ -109,5 +118,7 @@ interface VestedRewardsDistributionLike { } interface ChainlogLike { + function getAddress(bytes32 key) external view returns (address); + function setAddress(bytes32 key, address addr) external; } diff --git a/script/phase-1b/02-UsdsSkyFarmingInit.s.sol b/script/phase-1b/02-UsdsSkyFarmingInit.s.sol index 437e258..a13ebc5 100644 --- a/script/phase-1b/02-UsdsSkyFarmingInit.s.sol +++ b/script/phase-1b/02-UsdsSkyFarmingInit.s.sol @@ -19,7 +19,6 @@ import {Script} from "forge-std/Script.sol"; import {ScriptTools} from "dss-test/ScriptTools.sol"; import {Reader} from "../helpers/Reader.sol"; -import {VestInit, VestInitParams} from "../dependencies/VestInit.sol"; import { UsdsSkyFarmingInit, UsdsSkyFarmingInitParams, @@ -60,17 +59,12 @@ contract Phase1b_UsdsSkyFarmingInitScript is Script { vestTau: vestTau }); - VestInitParams memory vestInitCfg = VestInitParams({cap: type(uint256).max}); - address pauseProxy = chainlog.getAddress("MCD_PAUSE_PROXY"); vm.startBroadcast(); UsdsSkyFarmingInitSpell spell = new UsdsSkyFarmingInitSpell(); - bytes memory out = ProxyLike(pauseProxy).exec( - address(spell), - abi.encodeCall(spell.cast, (farmingCfg, vestInitCfg)) - ); + bytes memory out = ProxyLike(pauseProxy).exec(address(spell), abi.encodeCall(spell.cast, (farmingCfg))); vm.stopBroadcast(); @@ -85,11 +79,10 @@ contract Phase1b_UsdsSkyFarmingInitScript is Script { } contract UsdsSkyFarmingInitSpell { - function cast( - UsdsSkyFarmingInitParams memory farmingCfg, - VestInitParams calldata vestInitCfg - ) public returns (UsdsSkyFarmingInitResult memory) { - VestInit.init(farmingCfg.vest, vestInitCfg); + uint256 internal constant CAP = type(uint256).max; + + function cast(UsdsSkyFarmingInitParams memory farmingCfg) public returns (UsdsSkyFarmingInitResult memory) { + DssVestLike(farmingCfg.vest).file("cap", CAP); return UsdsSkyFarmingInit.init(farmingCfg); } } @@ -101,3 +94,7 @@ interface ProxyLike { interface ChainlogLike { function getAddress(bytes32 _key) external view returns (address addr); } + +interface DssVestLike { + function file(bytes32 _what, uint256 _data) external; +} diff --git a/script/phase-1b/03-UsdsSkyFarmingCheck.s.sol b/script/phase-1b/03-UsdsSkyFarmingCheck.s.sol index a755385..3dad1ab 100644 --- a/script/phase-1b/03-UsdsSkyFarmingCheck.s.sol +++ b/script/phase-1b/03-UsdsSkyFarmingCheck.s.sol @@ -16,12 +16,13 @@ pragma solidity ^0.8.16; import {Script} from "forge-std/Script.sol"; +import {ScriptTools} from "dss-test/ScriptTools.sol"; import {Reader} from "../helpers/Reader.sol"; contract Phase1b_UsdsSkyFarmingCheckScript is Script { function run() external returns (bool) { - Reader deps = new Reader(""); - deps.loadDependenciesOrConfig(); + Reader config = new Reader(ScriptTools.loadConfig()); + Reader deps = new Reader(ScriptTools.loadDependencies()); address admin = deps.envOrReadAddress("FOUNDRY_ADMIN", ".admin"); address sky = deps.envOrReadAddress("FOUNDRY_SKY", ".sky"); @@ -30,6 +31,9 @@ contract Phase1b_UsdsSkyFarmingCheckScript is Script { address rewards = deps.readAddress(".rewards"); address vest = deps.readAddress(".vest"); uint256 vestId = deps.readUint(".vestId"); + uint256 vestBgn = config.readUint(".vestBgn"); + uint256 vestTau = config.readUint(".vestTau"); + uint256 vestTot = config.readUint(".vestTot"); require(VestedRewardsDistributionLike(dist).dssVest() == vest, "VestedRewardsDistribution/invalid-vest"); require(VestedRewardsDistributionLike(dist).vestId() == vestId, "VestedRewardsDistribution/invalid-vest-id"); @@ -41,7 +45,7 @@ contract Phase1b_UsdsSkyFarmingCheckScript is Script { require(StakingRewardsLike(rewards).owner() == admin, "StakingRewards/admin-not-owner"); require(StakingRewardsLike(rewards).rewardsToken() == sky, "StakingRewards/invalid-rewards-token"); - require(StakingRewardsLike(rewards).stakingToken() == usds, "StakingRewards/invalid-rewards-token"); + require(StakingRewardsLike(rewards).stakingToken() == usds, "StakingRewards/invalid-staking-token"); require( StakingRewardsLike(rewards).rewardsDistribution() == dist, "StakingRewards/invalid-rewards-distribution" @@ -54,6 +58,9 @@ contract Phase1b_UsdsSkyFarmingCheckScript is Script { require(DssVestWithGemLike(vest).res(vestId) == 1, "DssVest/invalid-vest-res"); require(DssVestWithGemLike(vest).usr(vestId) == dist, "DssVest/wrong-dist"); require(DssVestWithGemLike(vest).mgr(vestId) == address(0), "DssVest/mgr-should-not-be-set"); + require(DssVestWithGemLike(vest).bgn(vestId) == vestBgn, "DssVest/invalid-bgn"); + require(DssVestWithGemLike(vest).fin(vestId) == vestBgn + vestTau, "DssVest/invalid-tau"); + require(DssVestWithGemLike(vest).tot(vestId) == vestTot, "DssVest/invalid-tot"); return true; } @@ -84,12 +91,18 @@ interface StakingRewardsLike { } interface DssVestWithGemLike { + function bgn(uint256 _id) external view returns (uint256); + + function fin(uint256 _id) external view returns (uint256); + function gem() external view returns (address); function mgr(uint256 _id) external view returns (address); function res(uint256 _id) external view returns (uint256); + function tot(uint256 _id) external view returns (uint256); + function usr(uint256 _id) external view returns (address); function valid(uint256 _id) external view returns (bool);