diff --git a/lib/dss-test b/lib/dss-test
index 36ff4adbc..a8a7b151c 160000
--- a/lib/dss-test
+++ b/lib/dss-test
@@ -1 +1 @@
-Subproject commit 36ff4adbcb35760614e0d2df864026991c23d028
+Subproject commit a8a7b151c39282d4ddab8cb4ead2d80342df588f
diff --git a/src/DssSpell.sol b/src/DssSpell.sol
index ffb647de1..53eaa92a1 100644
--- a/src/DssSpell.sol
+++ b/src/DssSpell.sol
@@ -14,55 +14,40 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-pragma solidity 0.8.16;
+pragma solidity ^0.8.16;
import "dss-exec-lib/DssExec.sol";
import "dss-exec-lib/DssAction.sol";
import { DssInstance, MCD } from "dss-test/MCD.sol";
-import { VatAbstract } from "dss-interfaces/dss/VatAbstract.sol";
-
-// Note: source code matches https://github.com/makerdao/dss-flappers/blob/95431f3d4da66babf81c6e1138bd05f5ddc5e516/deploy/FlapperInit.sol
-import { FlapperInit, FarmConfig } from "src/dependencies/dss-flappers/FlapperInit.sol";
-
-// Note: source code matches https://github.com/makerdao/lockstake/blob/7c71318623f5d6732457fd0c247a1f1760960011/deploy/LockstakeInit.sol
-import { LockstakeInit, LockstakeConfig } from "src/dependencies/lockstake/LockstakeInit.sol";
-// Note: source code matches https://github.com/makerdao/lockstake/blob/7c71318623f5d6732457fd0c247a1f1760960011/deploy/LockstakeInstance.sol
-import { LockstakeInstance } from "src/dependencies/lockstake/LockstakeInstance.sol";
-
-interface SkyLike {
- function mint(address to, uint256 value) external;
+import { BridgesConfig, TokenBridgeInit } from "./dependencies/base-token-bridge/TokenBridgeInit.sol";
+import { L1TokenBridgeInstance } from "./dependencies/base-token-bridge/L1TokenBridgeInstance.sol";
+import { L2TokenBridgeInstance } from "./dependencies/base-token-bridge/L2TokenBridgeInstance.sol";
+import { AllocatorSharedInstance, AllocatorIlkInstance } from "./dependencies/dss-allocator/AllocatorInstances.sol";
+import { AllocatorInit, AllocatorIlkConfig } from "./dependencies/dss-allocator/AllocatorInit.sol";
+
+interface DssLitePsmLike {
+ function kiss(address usr) external;
}
-interface RwaLiquidationOracleLike {
- function cull(bytes32 ilk, address urn) external;
- function tell(bytes32 ilk) external;
-}
-
-interface ProxyLike {
- function exec(address target, bytes calldata args) external payable returns (bytes memory out);
+interface MedianLike {
+ function lift(address[] memory a) external;
}
contract DssSpellAction is DssAction {
// Provides a descriptive tag for bot consumption
// This should be modified weekly to provide a summary of the actions
- // Hash: cast keccak -- "$(wget 'https://raw.githubusercontent.com/makerdao/community/7c7d7d16734407fdde827801ab4bbd6878560375/governance/votes/Executive%20vote%20-%20October%2017%2C%202024.md' -q -O - 2>/dev/null)"
+ // Hash: cast keccak -- "$(wget 'TODO' -q -O - 2>/dev/null)"
string public constant override description =
- "2024-10-17 MakerDAO Executive Spell | Hash: 0xa1e0345f807a0333170271e69caca6d384b3a715ccad597b8ad9502963eabd6f";
+ "2024-10-31 MakerDAO Executive Spell | Hash: TODO";
// Set office hours according to the summary
function officeHours() public pure override returns (bool) {
return true;
}
- // Note: by the previous convention it should be a comma-separated list of DAO resolutions IPFS hashes
- string public constant dao_resolutions = "QmYJUvw5xbAJmJknG2xUKDLe424JSTWQQhbJCnucRRjUv7";
-
// ---------- Math ----------
- uint256 internal constant MILLION = 10 ** 6;
- uint256 internal constant WAD = 10 ** 18;
uint256 internal constant RAY = 10 ** 27;
- uint256 internal constant RAD = 10 ** 45;
// ---------- Rates ----------
// Many of the settings that change weekly rely on the rate accumulator
@@ -75,334 +60,211 @@ contract DssSpellAction is DssAction {
// https://ipfs.io/ipfs/QmVp4mhhbwWGTfbh2BzwQB9eiBrQBKiqcPRZCaAxNUaar6
//
// uint256 internal constant X_PCT_RATE = ;
- uint256 internal constant TWELVE_PCT_RATE = 1000000003593629043335673582;
-
- // ---------- Contracts ----------
- address internal immutable MCD_VAT = DssExecLib.vat();
- address internal immutable MCD_VOW = DssExecLib.vow();
- address internal immutable MCD_GOV = DssExecLib.mkr();
- address internal immutable MIP21_LIQUIDATION_ORACLE = DssExecLib.getChangelogAddress("MIP21_LIQUIDATION_ORACLE");
- address internal immutable RWA007_A_URN = DssExecLib.getChangelogAddress("RWA007_A_URN");
- address internal immutable RWA014_A_URN = DssExecLib.getChangelogAddress("RWA014_A_URN");
- address internal immutable PIP_MKR = DssExecLib.getChangelogAddress("PIP_MKR");
- address internal immutable VOTE_DELEGATE_PROXY_FACTORY = DssExecLib.getChangelogAddress("VOTE_DELEGATE_PROXY_FACTORY");
- address internal immutable MCD_SPLIT = DssExecLib.getChangelogAddress("MCD_SPLIT");
- address internal immutable USDS_JOIN = DssExecLib.getChangelogAddress("USDS_JOIN");
- address internal immutable USDS = DssExecLib.getChangelogAddress("USDS");
- address internal immutable MKR_SKY = DssExecLib.getChangelogAddress("MKR_SKY");
- address internal immutable SKY = DssExecLib.getChangelogAddress("SKY");
- address internal constant NEW_PIP_MKR = 0x4F94e33D0D74CfF5Ca0D3a66F1A650628551C56b;
- address internal constant VOTE_DELEGATE_FACTORY = 0xC3D809E87A2C9da4F6d98fECea9135d834d6F5A0;
- address internal constant REWARDS_LSMKR_USDS = 0x92282235a39bE957fF1f37619fD22A9aE5507CB1;
- address internal constant LOCKSTAKE_MKR = 0xb4e0e45e142101dC3Ed768bac219fC35EDBED295;
- address internal constant LOCKSTAKE_ENGINE = 0x2b16C07D5fD5cC701a0a871eae2aad6DA5fc8f12;
- address internal constant LOCKSTAKE_CLIP = 0xA85621D35cAf9Cf5C146D2376Ce553D7B78A6239;
- address internal constant LOCKSTAKE_CLIP_CALC = 0xf13cF3b39823CcfaE6C2354dA56416C80768474e;
-
- // ---------- Wallets ----------
- address internal constant AAVE_V3_TREASURY = 0x464C71f6c2F760DdA6093dCB91C24c39e5d6e18c;
- address internal constant EARLY_BIRD_REWARDS = 0x14D98650d46BF7679BBD05D4f615A1547C87Bf68;
-
- // ---------- Spark Proxy Spell ----------
- // Spark Proxy: https://github.com/marsfoundation/sparklend-deployments/blob/bba4c57d54deb6a14490b897c12a949aa035a99b/script/output/1/primary-sce-latest.json#L2
- address internal constant SPARK_PROXY = 0x3300f198988e4C9C63F75dF86De36421f06af8c4;
- address internal constant SPARK_SPELL = 0xcc3B9e79261A7064A0f734Cc749A8e3762e0a187;
+ uint256 internal constant FIVE_PT_TWO_PCT_RATE = 1000000001607468111246255079;
+
+ // --- Math ---
+ uint256 internal constant RAD = 10 ** 45;
+
+ address internal immutable USDS = DssExecLib.getChangelogAddress("USDS");
+ address internal immutable SUSDS = DssExecLib.getChangelogAddress("SUSDS");
+ address internal immutable ILK_REGISTRY = DssExecLib.getChangelogAddress("ILK_REGISTRY");
+ address internal immutable LITE_PSM = DssExecLib.getChangelogAddress("MCD_LITE_PSM_USDC_A");
+
+ // ---------- BASE Token Bridge ----------
+ // Mainnet addresses
+ address internal constant BASE_GOV_RELAY = 0x1Ee0AE8A993F2f5abDB51EAF4AC2876202b65c3b;
+ address internal constant BASE_ESCROW = 0x7F311a4D48377030bD810395f4CCfC03bdbe9Ef3;
+ address internal constant BASE_TOKEN_BRIDGE = 0xA5874756416Fa632257eEA380CAbd2E87cED352A;
+ address internal constant BASE_TOKEN_BRIDGE_IMP = 0xaeFd31c2e593Dc971f9Cb42cBbD5d4AD7F1970b6;
+ address internal constant MESSANGER = 0x866E82a600A1414e583f7F13623F1aC5d58b0Afa;
+ // BASE addresses
+ address internal constant BASE_GOV_RELAY_L2 = 0xdD0BCc201C9E47c6F6eE68E4dB05b652Bb6aC255;
+ address internal constant BASE_TOKEN_BRIDGE_L2 = 0xee44cdb68D618d58F75d9fe0818B640BD7B8A7B7;
+ address internal constant BASE_TOKEN_BRIDGE_IMP_L2 = 0x289A37BE5D6CCeF7A8f2b90535B3BB6bD3905f72;
+ address internal constant USDS_L2 = 0x820C137fa70C8691f0e44Dc420a5e53c168921Dc;
+ address internal constant SUSDS_L2 = 0x5875eEE11Cf8398102FdAd704C9E96607675467a;
+ address internal constant SPELL_L2 = 0x6f29C3A29A3F056A71FB0714551C8D3547268D62;
+ address internal constant MESSANGER_L2 = 0x4200000000000000000000000000000000000007;
+
+ // ---------- Allocator System ----------
+ address internal constant ALLOCATOR_ROLES = 0x9A865A710399cea85dbD9144b7a09C889e94E803;
+ address internal constant ALLOCATOR_REGISTRY = 0xCdCFA95343DA7821fdD01dc4d0AeDA958051bB3B;
+ address internal constant PIP_ALLOCATOR_SPARK_A = 0xc7B91C401C02B73CBdF424dFaaa60950d5040dB7;
+ address internal constant ALLOCATOR_SPARK_BUFFER = 0xc395D150e71378B47A1b8E9de0c1a83b75a08324;
+ address internal constant ALLOCATOR_SPARK_VAULT = 0x691a6c29e9e96dd897718305427Ad5D534db16BA;
+ address internal constant ALLOCATOR_SPARK_OWNER = 0xBE8E3e3618f7474F8cB1d074A26afFef007E98FB;
+ address internal constant SPARK_ALM_PROXY = 0x1601843c5E9bC251A3272907010AFa41Fa18347E;
+ address internal constant SPARK_PROXY = 0x3300f198988e4C9C63F75dF86De36421f06af8c4;
+
+ // ---------- Medians and Validators ----------
+ address internal constant ETH_GLOBAL_VALIDATOR = 0xcfC62b2269521e3212Ce1b6670caE6F0e34E8bF3;
+ address internal constant MANTLE_VALIDATOR = 0xFa6eb665e067759ADdE03a8E6bD259adBd1D70c9;
+ address internal constant NETHERMIND_VALIDATOR = 0x91242198eD62F9255F2048935D6AFb0C2302D147;
+ address internal constant EULER_VALIDATOR = 0x1DCB8CcC022938e102814F1A299C7ae48A8BAAf6;
+ address internal constant BTC_USD_MEDIAN = 0xe0F30cb149fAADC7247E953746Be9BbBB6B5751f;
+ address internal constant ETH_USD_MEDIAN = 0x64DE91F5A373Cd4c28de3600cB34C7C6cE410C85;
+ address internal constant WSTETH_USD_MEDIAN = 0x2F73b6567B866302e132273f67661fB89b5a66F2;
+ address internal constant MKR_USD_MEDIAN = 0xdbBe5e9B1dAa91430cF0772fCEbe53F6c6f137DF;
+
function actions() public override {
// Note: multple actions in the spell depend on DssInstance
DssInstance memory dss = MCD.loadFromChainlog(DssExecLib.LOG);
- // ---------- Setup new MkrOsm ----------
- // Forum: https://forum.sky.money/t/atlas-weekly-cycle-edit-proposal-week-of-october-14-2024-01/25324
- // Poll: https://vote.makerdao.com/polling/QmUm8Krq
-
- // Whitelist MkrOsm to read from current PIP_MKR using `DssExecLib.addReaderToWhitelist` with the following parameters:
- // Set parameter address _oracle: PIP_MKR address from chainlog (0xdbbe5e9b1daa91430cf0772fcebe53f6c6f137df)
- // Set parameter address _reader: 0x4F94e33D0D74CfF5Ca0D3a66F1A650628551C56b
- DssExecLib.addReaderToWhitelist(PIP_MKR, NEW_PIP_MKR);
-
- // Set MkrOsm as "PIP_MKR" in the chainlog using the following parameters:
- // Set parameter bytes32 _key: "PIP_MKR"
- // Set parameter address _val: 0x4F94e33D0D74CfF5Ca0D3a66F1A650628551C56b
- DssExecLib.setChangelogAddress("PIP_MKR", NEW_PIP_MKR);
-
- // ---------- Setup new VoteDelegateFactory ----------
- // Forum: https://forum.sky.money/t/atlas-weekly-cycle-edit-proposal-week-of-october-14-2024-01/25324
- // Poll: https://vote.makerdao.com/polling/QmUm8Krq
-
- // Rename "VOTE_DELEGATE_PROXY_FACTORY" to "VOTE_DELEGATE_FACTORY_LEGACY" in chainlog:
- // Note: this is a meta instruction, actual instructions are below
-
- // Call DssExecLib.setChangelogAddress with the following parameters:
- // Set parameter bytes32 _key: "VOTE_DELEGATE_FACTORY_LEGACY"
- // Set parameter address _val: VOTE_DELEGATE_PROXY_FACTORY address (0xd897f108670903d1d6070fcf818f9db3615af272) from the chainlog
- DssExecLib.setChangelogAddress("VOTE_DELEGATE_FACTORY_LEGACY", VOTE_DELEGATE_PROXY_FACTORY);
-
- // Call CHAINLOG.removeAddress with the following parameters:
- // Set parameter bytes32 _key: "VOTE_DELEGATE_PROXY_FACTORY"
- dss.chainlog.removeAddress("VOTE_DELEGATE_PROXY_FACTORY");
-
- // Set "VOTE_DELEGATE_FACTORY" in the chainlog to 0xC3D809E87A2C9da4F6d98fECea9135d834d6F5A0
- DssExecLib.setChangelogAddress("VOTE_DELEGATE_FACTORY", VOTE_DELEGATE_FACTORY);
-
- // ---------- Setup Lockstake Engine ----------
- // Forum: https://forum.sky.money/t/atlas-weekly-cycle-edit-proposal-week-of-october-14-2024-01/25324
- // Poll: https://vote.makerdao.com/polling/QmUm8Krq
-
- // SBE Parameter Changes
- // Note: this is a subheading, actual instructions are below
-
- // Decrease splitter "burn" rate by 30% from 100% to 70% with the following parameters:
- // Decrease splitter "burn" with address _base: MCD_SPLIT from chainlog
- // Decrease splitter "burn" with bytes32 _what: "burn"
- // Decrease splitter "burn" with uint256 _amt: 70%
- DssExecLib.setValue(MCD_SPLIT, "burn", 70 * WAD / 100);
-
- // Increase vow.hump by 5 million DAI, from 55 million DAI to 60 million DAI
- DssExecLib.setValue(MCD_VOW, "hump", 60 * MILLION * RAD);
-
- // Increase splitter.hop by 4,014 seconds, from 11,635 seconds to 15,649 seconds.
- DssExecLib.setValue(MCD_SPLIT, "hop", 15_649);
-
- // Set Flapper farm by calling FlapperInit.setFarm with the following parameters:
- FlapperInit.setFarm(
-
- // Note: FlapperInit.setFarm requires DssInstance
- dss,
-
- // Set Flapper farm with address farm_ : 0x92282235a39bE957fF1f37619fD22A9aE5507CB1
- REWARDS_LSMKR_USDS,
-
- FarmConfig({
- // Set Flapper farm with address splitter: MCD_SPLIT from chainlog
- splitter: MCD_SPLIT,
-
- // Set Flapper farm with address usdsJoin: USDS_JOIN from chainlog
- usdsJoin: USDS_JOIN,
-
- // Set Flapper farm with uint256 hop: 15,649
- hop: 15_649 seconds,
-
- // Set Flapper farm with bytes32 prevChainlogKey: bytes32(0)
- prevChainlogKey: bytes32(0),
-
- // Set Flapper farm with chainlogKey: "REWARDS_LSMKR_USDS"
- chainlogKey: "REWARDS_LSMKR_USDS"
- })
- );
-
- // "Under the hood" actions for setting flapper:
- // LsMkrUsdsFarm will be set as "farm" in MCD_SPLIT
- // MCD_SPLIT will be set as "rewardsDistribution" in LsMkrUsdsFarm
- // Provided "hop" will be set as "rewardsDuration" in LsMkrUsdsFarm
- // New chainlog key REWARDS_LSMKR_USDS will be added
- // Note: above instructions are taken inside FlapperInit.setFarm method
-
- // Note: prepare "farms" variable used inside Lockstake init call below
- address[] memory farms = new address[](1);
- farms[0] = REWARDS_LSMKR_USDS;
-
- // Init Lockstake Engine by calling LockstakeInit.initLockstake with the following parameters:
- LockstakeInit.initLockstake(
-
- // Note: LockstakeInit.initLockstake requires DssInstance
- dss,
-
- LockstakeInstance({
- // Init Lockstake Engine with address lsmkr: 0xb4e0e45e142101dC3Ed768bac219fC35EDBED295
- lsmkr: LOCKSTAKE_MKR,
-
- // Init Lockstake Engine with address engine: 0x2b16C07D5fD5cC701a0a871eae2aad6DA5fc8f12
- engine: LOCKSTAKE_ENGINE,
-
- // Init Lockstake Engine with address clipper: 0xA85621D35cAf9Cf5C146D2376Ce553D7B78A6239
- clipper: LOCKSTAKE_CLIP,
-
- // Init Lockstake Engine with address clipperCalc: 0xf13cF3b39823CcfaE6C2354dA56416C80768474e
- clipperCalc: LOCKSTAKE_CLIP_CALC
- }),
-
- LockstakeConfig({
- // Init Lockstake Engine with bytes32 ilk: "LSE-MKR-A"
- ilk: "LSE-MKR-A",
-
- // Init Lockstake Engine with address voteDelegateFactory: 0xC3D809E87A2C9da4F6d98fECea9135d834d6F5A0
- voteDelegateFactory: VOTE_DELEGATE_FACTORY,
-
- // Init Lockstake Engine with address usdsJoin: USDS_JOIN from chainlog
- usdsJoin: USDS_JOIN,
-
- // Init Lockstake Engine with address usds: USDS from chainlog
- usds: USDS,
-
- // Init Lockstake Engine with address mkr: MCD_GOV from chainlog
- mkr: MCD_GOV,
-
- // Init Lockstake Engine with address mkrSky: MKR_SKY from chainlog
- mkrSky: MKR_SKY,
-
- // Init Lockstake Engine with address sky: SKY from chainlog
- sky: SKY,
-
- // Init Lockstake Engine with address[] farms: 0x92282235a39bE957fF1f37619fD22A9aE5507CB1
- farms: farms,
-
- // Init Lockstake Engine with uint256 fee: 5%
- fee: 5 * WAD / 100,
-
- // Init Lockstake Engine with uint256 maxLine: 20 million DAI
- maxLine: 20 * MILLION * RAD,
-
- // Init Lockstake Engine with uint256 gap: 5 million
- gap: 5 * MILLION * RAD,
-
- // Init Lockstake Engine with uint256 ttl: 16 hours
- ttl: 16 hours,
-
- // Init Lockstake Engine with uint256 dust: 30,000 DAI
- dust: 30_000 * RAD,
-
- // Init Lockstake Engine with uint256 duty: 12%
- duty: TWELVE_PCT_RATE,
-
- // Init Lockstake Engine with uint256 mat: 200%
- mat: 200 * RAY / 100,
-
- // Init Lockstake Engine with uint256 buf: 1.20
- buf: 120 * RAY / 100,
-
- // Init Lockstake Engine with uint256 tail: 6,000 seconds
- tail: 6_000 seconds,
-
- // Init Lockstake Engine with uint256 cusp: 0.40
- cusp: 40 * RAY / 100,
-
- // Init Lockstake Engine with uint256 chip: 0.1%
- chip: 1 * WAD / 1000,
-
- // Init Lockstake Engine with uint256 tip: 300 DAI
- tip: 300 * RAD,
-
- // Init Lockstake Engine with uint256 stopped: 0
- stopped: 0,
-
- // Init Lockstake Engine with uint256 chop: 8%
- chop: 108 * WAD / 100,
-
- // Init Lockstake Engine with uint256 hole: 3 million DAI
- hole: 3 * MILLION * RAD,
-
- // Init Lockstake Engine with uint256 tau: 0
- tau: 0,
-
- // Init Lockstake Engine with uint256 cut: 0.99
- cut: 99 * RAY / 100,
-
- // Init Lockstake Engine with uint256 step: 60 seconds
- step: 60 seconds,
-
- // Init Lockstake Engine with bool lineMom: true
- lineMom: true,
-
- // Init Lockstake Engine with uint256 tolerance: 0.5
- tolerance: 5 * RAY / 10,
-
- // Init Lockstake Engine with string name: "LockstakeMkr"
- name: "LockstakeMkr",
-
- // Init Lockstake Engine with string symbol: "lsMKR"
- symbol: "lsMKR"
- })
- );
-
- // "Under the hood" actions for Init Lockstake Engine:
- // New collateral type "LSE-MKR-A" will be added to "vat", "jug", "spotter", "dog" contracts
- // New collateral type "LSE-MKR-A" will be added to LINE_MOM
- // New collateral type "LSE-MKR-A" will be added to auto-line using provided maxLine, gap and ttl
- // New collateral type "LSE-MKR-A" will be added to ILK_REGISTRY with provided values ("name", "symbol") and the new ilk class 7
- // The new MKR OSM will allow MCD_SPOT, CLIPPER_MOM, LOCKSTAKE_CLIP, MCD_END to access its price.
- // PIP_MKR will be added to OSM_MOM
- // LockstakeClipper will be configured using provided values ("buf", "tail", "cusp", "chip", "tip", "stopped", "clip", "tolerance")
- // StairstepExponentialDecrease calc contract will be configured using provided values ("cut", "step")
- // The LsMkrUsdsFarm will be added to the LockstakeEngine as a first farm
- // LockstakeEngine will be authorized to access "vat"
- // LockstakeClipper will be authorized to access "vat" and LockstakeEngine
- // CLIPPER_MOM, MCD_DOG and MCD_END will be authorized to access LockstakeClipper
- // New chainlog keys LOCKSTAKE_MKR, LOCKSTAKE_ENGINE, LOCKSTAKE_CLIP and LOCKSTAKE_CLIP_CALC will be added
- // OSM_MOM will be authorized to access the new MKR OSM
- // Note: above instructions are taken inside LockstakeInit.initLockstake method
-
- // ---------- Fund Early Bird Rewards Multisig ----------
- // Forum: https://forum.sky.money/t/atlas-weekly-cycle-edit-proposal-week-of-october-14-2024-01/25324#p-99402-early-bird-bonus-3
- // Poll: https://vote.makerdao.com/polling/QmUm8Krq
-
- // Mint 27,222,832.80 SKY to 0x14D98650d46BF7679BBD05D4f615A1547C87Bf68
- SkyLike(SKY).mint(EARLY_BIRD_REWARDS, 27_222_832.80 ether); // Note: ether is only a keyword helper
-
- // ---------- Lower Deprecated RWA Debt Ceilings ----------
- // Forum: https://forum.sky.money/t/2024-10-17-expected-executive-contents-rwa-vault-changes/25323
-
- // Remove RWA007-A from Debt Ceiling Instant Access Module
- DssExecLib.removeIlkFromAutoLine("RWA007-A");
-
- // Note: in order to decrease global debt ceiling, we need to fetch current `line`
- (,,, uint256 line1,) = VatAbstract(MCD_VAT).ilks("RWA007-A");
-
- // Set RWA007-A Debt Ceiling to 0
- DssExecLib.setIlkDebtCeiling("RWA007-A", 0);
-
- // Initiate RWA007-A soft liquidation by calling `tell()`
- RwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).tell("RWA007-A");
-
- // Write-off the debt of RWA007-A and set its oracle price to 0 by calling `cull()`
- RwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).cull("RWA007-A", RWA007_A_URN);
-
- // Note: update the spot value in vat by propagating the price
- DssExecLib.updateCollateralPrice("RWA007-A");
-
- // Note: in order to decrease global debt ceiling, we need to fetch current `line`
- (,,, uint256 line2,) = VatAbstract(MCD_VAT).ilks("RWA014-A");
-
- // Reduce RWA014-A Debt Ceiling by 1.5 billion Dai from 1.5 billion Dai to 0
- DssExecLib.setIlkDebtCeiling("RWA014-A", 0);
-
- // Initiate RWA014-A soft liquidation by calling `tell()`
- RwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).tell("RWA014-A");
-
- // Write-off the debt of RWA014-A and set its oracle price to 0 by calling `cull()`
- RwaLiquidationOracleLike(MIP21_LIQUIDATION_ORACLE).cull("RWA014-A", RWA014_A_URN);
-
- // Note: update the spot value in vat by propagating the price
- DssExecLib.updateCollateralPrice("RWA014-A");
-
- // Note: decrease global line
- VatAbstract(MCD_VAT).file("Line", VatAbstract(MCD_VAT).Line() - (line1 + line2));
-
- // ---------- Pinwheel DAO Resolution ----------
- // Forum: https://forum.sky.money/t/coinbase-web3-wallet-legal-overview/24577/3
-
- // Approve DAO Resolution at QmYJUvw5xbAJmJknG2xUKDLe424JSTWQQhbJCnucRRjUv7
- // Note: see `dao_resolutions` public variable declared above
-
- // ---------- AAVE Revenue Share Payment ----------
- // Forum: https://forum.sky.money/t/spark-aave-revenue-share-calculation-payment-5-q3-2024/25286
-
- // AAVE Revenue Share - 234089 DAI - 0x464C71f6c2F760DdA6093dCB91C24c39e5d6e18c
- DssExecLib.sendPaymentFromSurplusBuffer(AAVE_V3_TREASURY, 234_089);
-
- // ---------- Spark Spell ----------
- // Forum: https://forum.sky.money/t/oct-3-2024-proposed-changes-to-spark-for-upcoming-spell/25293
- // Poll: https://vote.makerdao.com/polling/QmbHaA2G
- // Poll: https://vote.makerdao.com/polling/QmShWccA
- // Poll: https://vote.makerdao.com/polling/QmTksxrr
+ // ---------- Init Base Token Bridge for USDS and sUSDS tokens ----------
+ // Forum: TODO
+ //
+ // Set Escrow contract for L1 Bridge
+ // Register USDS, sUSDS on L1 Bridge
+ // Give max approval on Enscrow contract for L1 Bridge (USDS, sUSDS tokens)
+ // Execute L2 Bridge spell through Gov Relay (register nad set maxWithdrawals for USDS, sUSDS tokens on L2 Bridge)
+ // Set BASE_GOV_RELAY, BASE_ENSCROW, BASE_TOKEN_BRIDGE and BASE_TOKEN_BRIDGE_IMP ro CHAINLOG
+
+ // Mainnet Token Bridge instace
+ L1TokenBridgeInstance memory l1BridgeInstance = L1TokenBridgeInstance({
+ govRelay: BASE_GOV_RELAY,
+ escrow: BASE_ESCROW,
+ bridge: BASE_TOKEN_BRIDGE,
+ bridgeImp: BASE_TOKEN_BRIDGE_IMP
+ });
+
+ // Base Token Bridge instace
+ L2TokenBridgeInstance memory l2BridgeInstance = L2TokenBridgeInstance({
+ govRelay: BASE_GOV_RELAY_L2,
+ bridge: BASE_TOKEN_BRIDGE_L2,
+ bridgeImp: BASE_TOKEN_BRIDGE_IMP_L2,
+ spell: SPELL_L2
+ });
+
+ // Array with mainnet tokens
+ address[] memory l1Tokens = new address[](2);
+ l1Tokens[0] = USDS;
+ l1Tokens[1] = SUSDS;
+
+ // Array with Base tokens
+ address[] memory l2Tokens = new address[](2);
+ l2Tokens[0] = USDS_L2;
+ l2Tokens[1] = SUSDS_L2;
+
+ // Max withdrawals for Base tokens
+ uint256[] memory maxWithdrawals = new uint256[](2);
+ maxWithdrawals[0] = type(uint256).max;
+ maxWithdrawals[1] = type(uint256).max;
+
+ BridgesConfig memory bridgeCfg = BridgesConfig({
+ // Mainnet CrossDomain Messanger
+ l1Messenger: MESSANGER,
+ // Base CrossDomain Messanger
+ l2Messenger: MESSANGER_L2,
+ // Mainnet tokens (USDS, sUSDS)
+ l1Tokens: l1Tokens,
+ // Base tokens (USDS, sUSDS)
+ l2Tokens: l2Tokens,
+ // Max withdrawals for USDS, sUSDS
+ maxWithdraws: maxWithdrawals,
+ // Min gas for bridging
+ minGasLimit: 500_000,
+ // Chainlog key for Base Gov Relay Contract
+ govRelayCLKey: "BASE_GOV_RELAY",
+ // Chainlog key for Base Escrow Contract
+ escrowCLKey: "BASE_ESCROW",
+ // Chainlog key for Base Token Bridge Contract
+ l1BridgeCLKey: "BASE_TOKEN_BRIDGE",
+ // Chainlog key for Base Token Bridge Implementaion Contract
+ l1BridgeImpCLKey: "BASE_TOKEN_BRIDGE_IMP"
+ });
+
+ // Init Base Token Bridge for USDS and sUSDS
+ TokenBridgeInit.initBridges(dss, l1BridgeInstance, l2BridgeInstance, bridgeCfg);
+
+
+ // ---------- Init Allocator ILK for Spark Subdao ----------
+ // Forum: TODO
+ //
+ // Init ALLOCATOR-SPARK-A ilk on vat, jug and spotter
+ // Set duty on jug to 5.2%
+ // Set line on vat
+ // Increase Global Line on vat
+ // Setup AutoLine for ALLOCATOR-SPARK-A:
+ // line: 10_000_000
+ // gap: 2_500_000
+ // ttl: 86_400 seconds
+ // Set spotter.pip for ALLOCATOR-SPARK-A to AllocatorOracle contract
+ // Set spotter.mat for ALLOCATOR-SPARK-A to RAY
+ // poke ALLOCATOR-SPARK-A (spotter.poke)
+ // Add AllocatorBuffer address to AllocatorRegistry
+ // Initiate the allocator vault by calling vat.slip & vat.grab
+ // Set jug on AllocatorVault
+ // Allow vault to pull funds from the buffer by giving max USDS approval
+ // Set the allocator proxy as the ALLOCATOR-SPARK-A ilk admin instead of the Pause Proxy on AllocatorRoles
+ // Move ownership of AllocatorVault & AllocatorBuffer to AllocatorProxy (SparkProxy)
+ // Add Allocator contracts to chainlog (ALLOCATOR_ROLES, ALLOCATOR_REGISTRY, ALLOCATOR_SPARK_A_VAULT, ALLOCATOR_SPARK_A_BUFFER, PIP_ALLOCATOR_SPARK_A)
+ // Add ALLOCATOR-SPARK-A ilk to IlkRegistry
+
+
+ // Allocator shared contracts instance
+ AllocatorSharedInstance memory allocatorSharedInstance = AllocatorSharedInstance({
+ oracle: PIP_ALLOCATOR_SPARK_A,
+ roles: ALLOCATOR_ROLES,
+ registry: ALLOCATOR_REGISTRY
+ });
+
+ // Allocator ALLOCATOR-SPARK-A ilk contracts instance
+ AllocatorIlkInstance memory allocatorIlkInstance = AllocatorIlkInstance({
+ owner: ALLOCATOR_SPARK_OWNER,
+ vault: ALLOCATOR_SPARK_VAULT,
+ buffer: ALLOCATOR_SPARK_BUFFER
+ });
+
+ // Allocator init config
+ AllocatorIlkConfig memory allocatorIlkCfg = AllocatorIlkConfig({
+ // Init ilk for ALLOCATOR-SPARK-A
+ ilk : "ALLOCATOR-SPARK-A",
+ // jug.duty -> 5.2%
+ duty : FIVE_PT_TWO_PCT_RATE,
+ // Autoline line -> 10_000_000
+ maxLine : 10_000_000 * RAD,
+ // Autoline gap -> 10_000_000
+ gap : 10_000_000 * RAD,
+ // Autoline ttl -> 1 day
+ ttl : 86_400 seconds,
+ // Spark Proxy -> 0x1601843c5E9bC251A3272907010AFa41Fa18347E
+ allocatorProxy : SPARK_PROXY,
+ // Ilk Registry -> 0x5a464c28d19848f44199d003bef5ecc87d090f87
+ ilkRegistry : ILK_REGISTRY
+ });
+
+ // Init allocator shared contracts
+ AllocatorInit.initShared(dss, allocatorSharedInstance);
+
+ // Init allocator system for ALLOCATOR-SPARK-A ilk
+ AllocatorInit.initIlk(dss, allocatorSharedInstance, allocatorIlkInstance, allocatorIlkCfg);
+
+
+ // ---------- Whitelist Spark ALM Proxy on the PSM ----------
+ // Forum: TODO
+ DssLitePsmLike(LITE_PSM).kiss(SPARK_ALM_PROXY);
+
+
+ // ---------- Add new validators for Median (Medianizer) ----------
+ // Forum: TODO
+
+ address[] memory validators = new address[](4);
+ validators[0] = ETH_GLOBAL_VALIDATOR;
+ validators[1] = MANTLE_VALIDATOR;
+ validators[2] = NETHERMIND_VALIDATOR;
+ validators[3] = EULER_VALIDATOR;
+
+ MedianLike(BTC_USD_MEDIAN).lift(validators);
+ MedianLike(ETH_USD_MEDIAN).lift(validators);
+ MedianLike(WSTETH_USD_MEDIAN).lift(validators);
+ MedianLike(MKR_USD_MEDIAN).lift(validators);
- // Execute Spark Proxy Spell at 0xcc3B9e79261A7064A0f734Cc749A8e3762e0a187
- ProxyLike(SPARK_PROXY).exec(SPARK_SPELL, abi.encodeWithSignature("execute()"));
// ---------- Chainlog bump ----------
// Note: we have to patch chainlog version as new collateral is added
- DssExecLib.setChangelogVersion("1.19.2");
+ DssExecLib.setChangelogVersion("1.19.3");
}
}
diff --git a/src/DssSpell.t.base.sol b/src/DssSpell.t.base.sol
index b68430b99..b59b03576 100644
--- a/src/DssSpell.t.base.sol
+++ b/src/DssSpell.t.base.sol
@@ -2341,7 +2341,7 @@ contract DssSpellTestBase is Config, DssTest {
if (ward > 0) {
emit log_named_address(" Deployer Address", deployer);
emit log_named_string(" Affected Contract", contractName);
- fail("Error: Bad Auth");
+ revert("Error: Bad Auth");
}
}
}
diff --git a/src/DssSpell.t.sol b/src/DssSpell.t.sol
index 5c668e7e8..1ef502f11 100644
--- a/src/DssSpell.t.sol
+++ b/src/DssSpell.t.sol
@@ -49,9 +49,83 @@ interface SequencerLike {
function hasJob(address job) external view returns (bool);
}
-interface RwaLiquidationOracleLike {
- function good(bytes32 ilk) external view returns (bool);
- function ilks(bytes32) external view returns (string memory doc, address pip, uint48 tau, uint48 toc);
+interface AuthLike {
+ function wards(address) external view returns (uint256);
+}
+
+interface L1TokenBridgeLike {
+ function l1ToL2Token(address) external view returns (address);
+ function isOpen() external view returns (uint256);
+ function escrow() external view returns (address);
+ function otherBridge() external view returns (address);
+ function messenger() external view returns (address);
+ function version() external view returns (string memory);
+ function getImplementation() external view returns (address);
+ function bridgeERC20To(
+ address _localToken,
+ address _remoteToken,
+ address _to,
+ uint256 _amount,
+ uint32 _minGasLimit,
+ bytes memory _extraData
+ ) external;
+}
+
+interface L2TokenBridgeLike {
+ function l1ToL2Token(address) external view returns (address);
+ function isOpen() external view returns (uint256);
+ function escrow() external view returns (address);
+ function otherBridge() external view returns (address);
+ function messenger() external view returns (address);
+ function version() external view returns (string memory);
+ function maxWithdraws(address) external view returns (uint256);
+ function getImplementation() external view returns (address);
+ function bridgeERC20To(
+ address _localToken,
+ address _remoteToken,
+ address _to,
+ uint256 _amount,
+ uint32 _minGasLimit,
+ bytes memory _extraData
+ ) external;
+}
+
+interface BaseGovRelayLike {
+ function l2GovernanceRelay() external view returns (address);
+ function l1GovernanceRelay() external view returns (address);
+ function messenger() external view returns (address);
+}
+
+interface L2BridgeSpell {
+ function l2Bridge() external view returns (address);
+}
+
+interface AllocatorVaultLike {
+ function buffer() external view returns (address);
+ function draw(uint256 wad) external;
+ function ilk() external view returns (bytes32);
+ function jug() external view returns (address);
+ function roles() external view returns (address);
+ function usdsJoin() external view returns (address);
+ function vat() external view returns (address);
+ function wards(address) external view returns (uint256);
+ function wipe(uint256 wad) external;
+}
+
+interface AllocatorRegistryLike {
+ function buffers(bytes32) external view returns (address);
+}
+
+interface AllocatorRolesLike {
+ function ilkAdmins(bytes32) external view returns (address);
+}
+
+interface DssLitePsm {
+ function bud(address) external view returns (uint256);
+}
+
+interface MedianLike {
+ function orcl(address) external view returns (uint256);
}
contract DssSpellTest is DssSpellTestBase {
@@ -59,6 +133,7 @@ contract DssSpellTest is DssSpellTestBase {
RootDomain rootDomain;
OptimismDomain optimismDomain;
ArbitrumDomain arbitrumDomain;
+ OptimismDomain baseDomain;
// DO NOT TOUCH THE FOLLOWING TESTS, THEY SHOULD BE RUN ON EVERY SPELL
function testGeneral() public {
@@ -215,7 +290,7 @@ contract DssSpellTest is DssSpellTestBase {
//assertEq(OsmAbstract(0xF15993A5C5BE496b8e1c9657Fd2233b579Cd3Bc6).wards(ORACLE_WALLET01), 1);
}
- function testRemoveChainlogValues() public { // add the `skipped` modifier to skip
+ function testRemoveChainlogValues() public skipped { // add the `skipped` modifier to skip
string[1] memory removedKeys = [
"VOTE_DELEGATE_PROXY_FACTORY"
];
@@ -224,9 +299,9 @@ contract DssSpellTest is DssSpellTestBase {
try chainLog.getAddress(_stringToBytes32(removedKeys[i])) {
} catch Error(string memory errmsg) {
if (_cmpStr(errmsg, "dss-chain-log/invalid-key")) {
- fail(_concat("TestError/key-to-remove-does-not-exist: ", removedKeys[i]));
+ revert(_concat("TestError/key-to-remove-does-not-exist: ", removedKeys[i]));
} else {
- fail(errmsg);
+ revert(errmsg);
}
}
}
@@ -237,14 +312,14 @@ contract DssSpellTest is DssSpellTestBase {
for (uint256 i = 0; i < removedKeys.length; i++) {
try chainLog.getAddress(_stringToBytes32(removedKeys[i])) {
- fail(_concat("TestError/key-not-removed: ", removedKeys[i]));
+ revert(_concat("TestError/key-not-removed: ", removedKeys[i]));
} catch Error(string memory errmsg) {
assertTrue(
_cmpStr(errmsg, "dss-chain-log/invalid-key"),
_concat("TestError/key-not-removed: ", removedKeys[i])
);
} catch {
- fail(_concat("TestError/unknown-reason: ", removedKeys[i]));
+ revert(_concat("TestError/unknown-reason: ", removedKeys[i]));
}
}
}
@@ -281,7 +356,7 @@ contract DssSpellTest is DssSpellTestBase {
);
}
- function testLockstakeIlkIntegration() public { // add the `skipped` modifier to skip
+ function testLockstakeIlkIntegration() public skipped { // add the `skipped` modifier to skip
_vote(address(spell));
_scheduleWaitAndCast(address(spell));
assertTrue(spell.done(), "TestError/spell-not-done");
@@ -349,7 +424,7 @@ contract DssSpellTest is DssSpellTestBase {
}
}
- function testOsmReaders() public { // add the `skipped` modifier to skip
+ function testOsmReaders() public skipped { // add the `skipped` modifier to skip
address OSM = addr.addr("PIP_MKR");
address[4] memory newReaders = [
addr.addr("MCD_SPOT"),
@@ -371,7 +446,7 @@ contract DssSpellTest is DssSpellTestBase {
}
}
- function testMedianReaders() public { // add the `skipped` modifier to skip
+ function testMedianReaders() public skipped { // add the `skipped` modifier to skip
address median = chainLog.getAddress("PIP_MKR"); // PIP_MKR before spell
address[1] memory newReaders = [
addr.addr('PIP_MKR') // PIP_MKR after spell
@@ -395,7 +470,7 @@ contract DssSpellTest is DssSpellTestBase {
bytes32 ward;
}
- function testNewAuthorizations() public { // add the `skipped` modifier to skip
+ function testNewAuthorizations() public skipped { // add the `skipped` modifier to skip
Authorization[9] memory newAuthorizations = [
Authorization({ base: "MCD_VAT", ward: "LOCKSTAKE_ENGINE" }),
Authorization({ base: "MCD_VAT", ward: "LOCKSTAKE_CLIP" }),
@@ -596,7 +671,7 @@ contract DssSpellTest is DssSpellTestBase {
int256 sky;
}
- function testPayments() public { // add the `skipped` modifier to skip
+ function testPayments() public skipped { // add the `skipped` modifier to skip
// For each payment, create a Payee object with:
// the address of the transferred token,
// the destination address,
@@ -936,7 +1011,7 @@ contract DssSpellTest is DssSpellTestBase {
assertEq(Art, 0, "GUSD-A Art is not 0");
}
- function testDaoResolutions() public { // add the `skipped` modifier to skip
+ function testDaoResolutions() public skipped { // add the `skipped` modifier to skip
// For each resolution, add IPFS hash as item to the resolutions array
// Initialize the array with the number of resolutions
string[1] memory resolutions = [
@@ -955,7 +1030,7 @@ contract DssSpellTest is DssSpellTestBase {
}
// SPARK TESTS
- function testSparkSpellIsExecuted() public { // add the `skipped` modifier to skip
+ function testSparkSpellIsExecuted() public skipped { // add the `skipped` modifier to skip
address SPARK_PROXY = addr.addr('SPARK_PROXY');
address SPARK_SPELL = 0xcc3B9e79261A7064A0f734Cc749A8e3762e0a187;
@@ -974,48 +1049,257 @@ contract DssSpellTest is DssSpellTestBase {
}
// SPELL-SPECIFIC TESTS GO BELOW
+ L2TokenBridgeLike immutable l2bridge = L2TokenBridgeLike( 0xee44cdb68D618d58F75d9fe0818B640BD7B8A7B7);
+ BaseGovRelayLike immutable l2govRelay = BaseGovRelayLike( 0xdD0BCc201C9E47c6F6eE68E4dB05b652Bb6aC255);
+ L2BridgeSpell immutable l2spell = L2BridgeSpell( 0x6f29C3A29A3F056A71FB0714551C8D3547268D62);
+ GemAbstract immutable l2usds = GemAbstract( 0x820C137fa70C8691f0e44Dc420a5e53c168921Dc);
+ GemAbstract immutable l2susds = GemAbstract( 0x5875eEE11Cf8398102FdAd704C9E96607675467a);
+ GemAbstract immutable susd = GemAbstract( addr.addr("SUSDS"));
+ L1TokenBridgeLike immutable l1bridge = L1TokenBridgeLike( addr.addr("BASE_TOKEN_BRIDGE"));
+ BaseGovRelayLike immutable l1govRelay = BaseGovRelayLike( addr.addr("BASE_GOV_RELAY"));
+ address immutable L1_ESCROW = addr.addr("BASE_ESCROW");
+ address immutable L1_BRIDGE_IMP = addr.addr("BASE_TOKEN_BRIDGE_IMP");
+ address constant L2_BRIDGE_IMP = 0x289A37BE5D6CCeF7A8f2b90535B3BB6bD3905f72;
+ address constant MESSENGER = 0x866E82a600A1414e583f7F13623F1aC5d58b0Afa;
+ address constant L2_MESSANGER = 0x4200000000000000000000000000000000000007;
+
+ address immutable PIP_ALLOCATOR_SPARK = addr.addr("PIP_ALLOCATOR_SPARK_A");
+ address immutable ALLOCATOR_ROLES = addr.addr("ALLOCATOR_ROLES");
+ address immutable ALLOCATOR_REGISTRY = addr.addr("ALLOCATOR_REGISTRY");
+ address immutable ALLOCATOR_SPARK_BUFFER = addr.addr("ALLOCATOR_SPARK_A_BUFFER");
+ address immutable ALLOCATOR_SPARK_VAULT = addr.addr("ALLOCATOR_SPARK_A_VAULT");
+ address immutable ALLOCATOR_SPARK_PROXY = 0x1601843c5E9bC251A3272907010AFa41Fa18347E;
+ bytes32 constant ALLOCATOR_ILK = "ALLOCATOR-SPARK-A";
+
+ address immutable LITE_PSM = addr.addr("MCD_LITE_PSM_USDC_A");
+
+ // ---------- Medians and Validators ----------
+ address constant ETH_GLOBAL_VALIDATOR = 0xcfC62b2269521e3212Ce1b6670caE6F0e34E8bF3;
+ address constant MANTLE_VALIDATOR = 0xFa6eb665e067759ADdE03a8E6bD259adBd1D70c9;
+ address constant NETHERMIND_VALIDATOR = 0x91242198eD62F9255F2048935D6AFb0C2302D147;
+ address constant EULER_VALIDATOR = 0x1DCB8CcC022938e102814F1A299C7ae48A8BAAf6;
+ address constant BTC_USD_MEDIAN = 0xe0F30cb149fAADC7247E953746Be9BbBB6B5751f;
+ address constant ETH_USD_MEDIAN = 0x64DE91F5A373Cd4c28de3600cB34C7C6cE410C85;
+ address constant WSTETH_USD_MEDIAN = 0x2F73b6567B866302e132273f67661fB89b5a66F2;
+ address constant MKR_USD_MEDIAN = 0xdbBe5e9B1dAa91430cF0772fCEbe53F6c6f137DF;
+
+ function testBaseTokenBridge() public {
+ _setupRootDomain();
+ baseDomain = new OptimismDomain(config, getChain("base"), rootDomain);
+
+ // ------ Sanity checks -------
+
+ baseDomain.selectFork();
+
+ require(l2bridge.isOpen() == 1, "L2BaseTokenBridge/not-open");
+ require(l2bridge.otherBridge() == address(l1bridge), "L2BaseTokenBridge/other-bridge-mismatch");
+ require(keccak256(bytes(l2bridge.version())) == keccak256("1"), "L2BaseTokenBridge/version-does-not-match");
+ require(l2bridge.getImplementation() == L2_BRIDGE_IMP, "L2BaseTokenBridge/imp-does-not-match");
+ require(l2bridge.messenger() == L2_MESSANGER, "L2BaseTokenBridge/l2-bridge-messenger-mismatch");
+ require(l2govRelay.l1GovernanceRelay() == address(l1govRelay), "L2BaseGovRelay/l2-gov-relay-mismatch");
+ require(l2govRelay.messenger() == L2_MESSANGER, "L2BaseGovRelay/l2-gov-relay-messenger-mismatch");
+ require(l2spell.l2Bridge() == address(l2bridge), "L2Spell/l2-bridge-mismatch");
+
+ rootDomain.selectFork();
+
+ require(keccak256(bytes(l1bridge.version())) == keccak256("1"), "BaseTokenBridge/version-does-not-match");
+ require(l1bridge.getImplementation() == L1_BRIDGE_IMP, "BaseTokenBridge/imp-does-not-match");
+ require(l1bridge.isOpen() == 1, "BaseTokenBridge/not-open");
+ require(l1bridge.otherBridge() == address(l2bridge), "BaseTokenBridge/other-bridge-mismatch");
+ require(l1bridge.messenger() == MESSENGER, "BaseTokenBridge/l1-bridge-messenger-mismatch");
+ require(l1govRelay.l2GovernanceRelay() == address(l2govRelay), "BaseGovRelay/l2-gov-relay-mismatch");
+ require(l1govRelay.messenger() == MESSENGER, "BaseGovRelay/l1-gov-relay-messenger-mismatch");
- function testRwaTellAndCull() public {
- bytes32[2] memory ilks = [
- bytes32("RWA007-A"),
- bytes32("RWA014-A")
- ];
- RwaLiquidationOracleLike oracle = RwaLiquidationOracleLike(addr.addr("MIP21_LIQUIDATION_ORACLE"));
_vote(address(spell));
_scheduleWaitAndCast(address(spell));
- assertTrue(spell.done());
+ assertTrue(spell.done(), "TestError/spell-not-done");
- for (uint256 i = 0; i < ilks.length; i++) {
- bytes32 ilk = ilks[i];
- (, address pip, uint256 tau, uint256 toc) = oracle.ilks(ilk);
- assertGt(toc, 0, _concat("TestError/bad-toc-after-tell-", ilk));
- assertEq(tau, 0, _concat("TestError/bad-tau-after-tell-", ilk));
- assertFalse(oracle.good(ilk), _concat("TestError/still-good-after-tell-", ilk));
- uint256 price = uint256(DSValueAbstract(pip).read());
- assertEq(price, 0, _concat("TestError/non-zero-oracle-price-after-cull-", ilk));
+ require(l1bridge.escrow() == L1_ESCROW, "BaseTokenBridge/escrow-does-not-match");
+ // // test tokens
+ assertEq(usds.allowance(L1_ESCROW, address(l1bridge)), type(uint256).max);
+ assertEq(l1bridge.l1ToL2Token(address(address(usds))), address(l2usds));
- (uint256 Art,, uint256 spot,,) = vat.ilks(ilk);
- assertEq(Art, 0, _concat("TestError/non-zero-total-debt-after-cull-", ilk));
- assertEq(spot, 0, _concat("TestError/non-zero-spot-price-after-cull-", ilk));
- }
+ assertEq(susds.allowance(L1_ESCROW, address(l1bridge)), type(uint256).max);
+ assertEq(l1bridge.l1ToL2Token(address(address(susds))), address(l2susds));
+
+
+ // switch to Optimism domain and relay the spell from L1
+ // the `true` keeps us on Optimism rather than `rootDomain.selectFork()
+ baseDomain.relayFromHost(true);
+
+ // // test L2 side of initBridges
+ assertEq(l2bridge.l1ToL2Token(address(susds)), address(l2susds));
+ assertEq(l2bridge.maxWithdraws(address(l2susds)), type(uint256).max);
+
+ assertEq(l2bridge.l1ToL2Token(address(usds)), address(l2usds));
+ assertEq(l2bridge.maxWithdraws(address(l2usds)), type(uint256).max);
+
+ assertEq(AuthLike(address(l2susds)).wards(address(l2bridge)), 1);
+ assertEq(AuthLike(address(l2usds)).wards(address(l2bridge)), 1);
+
+
+ // ------- Test Deposit -------
+
+ rootDomain.selectFork();
+
+ deal(address(usds), address(this), 100 ether);
+ deal(address(susds), address(this), 100 ether);
+ assertEq(usds.balanceOf(address(this)), 100 ether);
+ assertEq(susds.balanceOf(address(this)), 100 ether);
+
+ usds.approve(address(l1bridge), 100 ether);
+ susds.approve(address(l1bridge), 100 ether);
+ uint256 escrowBeforeUsds = usds.balanceOf(L1_ESCROW);
+ uint256 escrowBeforesUsds = susds.balanceOf(L1_ESCROW);
+
+ l1bridge.bridgeERC20To(
+ address(usds),
+ address(l2usds),
+ address(0xb0b),
+ 100 ether,
+ 1_000_000,
+ ""
+ );
+ l1bridge.bridgeERC20To(
+ address(susds),
+ address(l2susds),
+ address(0xb0b),
+ 100 ether,
+ 1_000_000,
+ ""
+ );
+
+ assertEq(usds.balanceOf(address(this)), 0);
+ assertEq(usds.balanceOf(L1_ESCROW), escrowBeforeUsds + 100 ether);
+ assertEq(susds.balanceOf(address(this)), 0);
+ assertEq(susds.balanceOf(L1_ESCROW), escrowBeforesUsds + 100 ether);
+
+ baseDomain.relayFromHost(true);
+
+ assertEq(l2usds.balanceOf(address(0xb0b)), 100 ether);
+ assertEq(l2susds.balanceOf(address(0xb0b)), 100 ether);
+
+ // ------- Test Withdrawal -------
+
+ vm.startPrank(address(0xb0b));
+
+ l2usds.approve(address(l2bridge), 100 ether);
+ l2susds.approve(address(l2bridge), 100 ether);
+
+ l2bridge.bridgeERC20To(
+ address(l2usds),
+ address(usds),
+ address(0xced),
+ 100 ether,
+ 1_000_000,
+ ""
+ );
+ l2bridge.bridgeERC20To(
+ address(l2susds),
+ address(susds),
+ address(0xced),
+ 100 ether,
+ 1_000_000,
+ ""
+ );
+ vm.stopPrank();
+
+ assertEq(l2usds.balanceOf(address(0xb0b)), 0);
+ assertEq(l2susds.balanceOf(address(0xb0b)), 0);
+
+ baseDomain.relayToHost(true);
+
+ assertEq(usds.balanceOf(address(0xced)), 100 ether);
+ assertEq(susds.balanceOf(address(0xced)), 100 ether);
}
- function testNewOsmMomAddition() public {
- bytes32 ilk = "LSE-MKR-A";
- address osm = addr.addr("PIP_MKR");
+ function testSparkAllocator() public {
+ uint256 previousIlkRegistryCount = reg.count();
- assertEq(osmMom.osms(ilk), address(0), "TestError/osm-already-in-mom");
+ // Sanity checks
+ require(AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).ilk() == ALLOCATOR_ILK, "AllocatorInit/vault-ilk-mismatch");
+ require(AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).roles() == ALLOCATOR_ROLES, "AllocatorInit/vault-roles-mismatch");
+ require(AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).buffer() == ALLOCATOR_SPARK_BUFFER, "AllocatorInit/vault-buffer-mismatch");
+ require(AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).vat() == address(vat), "AllocatorInit/vault-vat-mismatch");
+ require(AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).usdsJoin() == address(usdsJoin), "AllocatorInit/vault-usds-join-mismatch");
_vote(address(spell));
_scheduleWaitAndCast(address(spell));
assertTrue(spell.done(), "TestError/spell-not-done");
- assertEq(osmMom.osms(ilk), osm, "TestError/osm-not-in-mom");
- assertEq(OsmAbstract(osm).stopped(), 0, "TestError/unexpected-stopped-before");
- vm.prank(chief.hat()); osmMom.stop(ilk);
- assertEq(OsmAbstract(osm).stopped(), 1, "TestError/unexpected-stopped-after");
+ (, uint256 rate, uint256 spot,,) = vat.ilks(ALLOCATOR_ILK);
+ assertEq(rate, RAY);
+ assertEq(spot, 10**18 * RAY * 10**9 / spotter.par());
+
+ (address pip,) = spotter.ilks(ALLOCATOR_ILK);
+ assertEq(pip, PIP_ALLOCATOR_SPARK);
+
+ assertEq(vat.gem(ALLOCATOR_ILK, ALLOCATOR_SPARK_VAULT), 0);
+ (uint256 ink, uint256 art) = vat.urns(ALLOCATOR_ILK, ALLOCATOR_SPARK_VAULT);
+ assertEq(ink, 1_000_000_000_000 * WAD);
+ assertEq(art, 0);
+
+ assertEq(AllocatorRegistryLike(ALLOCATOR_REGISTRY).buffers(ALLOCATOR_ILK), ALLOCATOR_SPARK_BUFFER);
+ assertEq(address(AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).jug()), address(jug));
+
+ assertEq(usds.allowance(ALLOCATOR_SPARK_BUFFER, ALLOCATOR_SPARK_VAULT), type(uint256).max);
+
+ assertEq(AllocatorRolesLike(ALLOCATOR_ROLES).ilkAdmins(ALLOCATOR_ILK), ALLOCATOR_SPARK_PROXY);
+
+ assertEq(AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).wards(pauseProxy), 0);
+ assertEq(AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).wards(ALLOCATOR_SPARK_PROXY), 1);
+
+ assertEq(AuthLike(ALLOCATOR_SPARK_BUFFER).wards(pauseProxy), 0);
+ assertEq(AuthLike(ALLOCATOR_SPARK_BUFFER).wards(ALLOCATOR_SPARK_PROXY), 1);
+
+ assertEq(reg.count(), previousIlkRegistryCount + 1);
+ assertEq(reg.pos(ALLOCATOR_ILK), previousIlkRegistryCount);
+ assertEq(reg.join(ALLOCATOR_ILK), address(0));
+ assertEq(reg.gem(ALLOCATOR_ILK), address(0));
+ assertEq(reg.dec(ALLOCATOR_ILK), 0);
+ assertEq(reg.class(ALLOCATOR_ILK), 5);
+ assertEq(reg.pip(ALLOCATOR_ILK), PIP_ALLOCATOR_SPARK);
+ assertEq(reg.xlip(ALLOCATOR_ILK), address(0));
+ assertEq(reg.name(ALLOCATOR_ILK), string("ALLOCATOR-SPARK-A"));
+ assertEq(reg.symbol(ALLOCATOR_ILK), string("ALLOCATOR-SPARK-A"));
+
+ // Draw & Wipe from Vault
+ vm.prank(address(ALLOCATOR_SPARK_PROXY));
+ AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).draw(1_000 * WAD);
+ assertEq(usds.balanceOf(ALLOCATOR_SPARK_BUFFER), 1_000 * WAD);
+
+ vm.prank(address(ALLOCATOR_SPARK_PROXY));
+ AllocatorVaultLike(ALLOCATOR_SPARK_VAULT).wipe(1_000 * WAD);
+ assertEq(usds.balanceOf(ALLOCATOR_SPARK_BUFFER), 0);
+ }
+
+ function testsWhitelistSparkProxyOnLitePsm() public {
+ _vote(address(spell));
+ _scheduleWaitAndCast(address(spell));
+ assertTrue(spell.done(), "TestError/spell-not-done");
+
+ assertEq(LitePsmLike(LITE_PSM).bud(ALLOCATOR_SPARK_PROXY), 1);
+ }
+
+ function testMedianValidators() public {
+ _vote(address(spell));
+ _scheduleWaitAndCast(address(spell));
+ assertTrue(spell.done(), "TestError/spell-not-done");
+
+ address[] memory validators = new address[](4);
+ validators[0] = ETH_GLOBAL_VALIDATOR;
+ validators[1] = MANTLE_VALIDATOR;
+ validators[2] = NETHERMIND_VALIDATOR;
+ validators[3] = EULER_VALIDATOR;
+
+ for (uint i = 0; i < validators.length; i++) {
+ assertEq(MedianLike(BTC_USD_MEDIAN).orcl(validators[1]), 1);
+ assertEq(MedianLike(ETH_USD_MEDIAN).orcl(validators[1]), 1);
+ assertEq(MedianLike(WSTETH_USD_MEDIAN).orcl(validators[1]), 1);
+ assertEq(MedianLike(MKR_USD_MEDIAN).orcl(validators[1]), 1);
+ }
}
}
diff --git a/src/dependencies/base-token-bridge/L1TokenBridgeInstance.sol b/src/dependencies/base-token-bridge/L1TokenBridgeInstance.sol
new file mode 100644
index 000000000..e45f7b261
--- /dev/null
+++ b/src/dependencies/base-token-bridge/L1TokenBridgeInstance.sol
@@ -0,0 +1,24 @@
+// SPDX-FileCopyrightText: © 2024 Dai Foundation
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.8.0;
+
+struct L1TokenBridgeInstance {
+ address govRelay;
+ address escrow;
+ address bridge;
+ address bridgeImp;
+}
\ No newline at end of file
diff --git a/src/dependencies/lockstake/LockstakeInstance.sol b/src/dependencies/base-token-bridge/L2TokenBridgeInstance.sol
similarity index 80%
rename from src/dependencies/lockstake/LockstakeInstance.sol
rename to src/dependencies/base-token-bridge/L2TokenBridgeInstance.sol
index d249711d0..1e427cef9 100644
--- a/src/dependencies/lockstake/LockstakeInstance.sol
+++ b/src/dependencies/base-token-bridge/L2TokenBridgeInstance.sol
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: © 2023 Dai Foundation
+// SPDX-FileCopyrightText: © 2024 Dai Foundation
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
@@ -16,9 +16,9 @@
pragma solidity >=0.8.0;
-struct LockstakeInstance {
- address lsmkr;
- address engine;
- address clipper;
- address clipperCalc;
-}
+struct L2TokenBridgeInstance {
+ address govRelay;
+ address bridge;
+ address bridgeImp;
+ address spell;
+}
\ No newline at end of file
diff --git a/src/dependencies/base-token-bridge/L2TokenBridgeSpell.sol b/src/dependencies/base-token-bridge/L2TokenBridgeSpell.sol
new file mode 100644
index 000000000..00fdd510c
--- /dev/null
+++ b/src/dependencies/base-token-bridge/L2TokenBridgeSpell.sol
@@ -0,0 +1,96 @@
+// SPDX-FileCopyrightText: © 2024 Dai Foundation
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.8.0;
+
+interface L2GovRelayLike {
+ function l1GovernanceRelay() external view returns (address);
+ function messenger() external view returns (address);
+}
+
+interface L2TokenBridgeLike {
+ function isOpen() external view returns (uint256);
+ function otherBridge() external view returns (address);
+ function messenger() external view returns (address);
+ function version() external view returns (string memory);
+ function getImplementation() external view returns (address);
+ function upgradeToAndCall(address, bytes memory) external;
+ function rely(address) external;
+ function deny(address) external;
+ function close() external;
+ function registerToken(address, address) external;
+ function setMaxWithdraw(address, uint256) external;
+}
+
+interface AuthLike {
+ function rely(address usr) external;
+}
+
+// A reusable L2 spell to be used by the L2GovernanceRelay to exert admin control over L2TokenBridge
+contract L2TokenBridgeSpell {
+ L2TokenBridgeLike public immutable l2Bridge;
+
+ constructor(address l2Bridge_) {
+ l2Bridge = L2TokenBridgeLike(l2Bridge_);
+ }
+
+ function upgradeToAndCall(address newImp, bytes memory data) external { l2Bridge.upgradeToAndCall(newImp, data); }
+ function rely(address usr) external { l2Bridge.rely(usr); }
+ function deny(address usr) external { l2Bridge.deny(usr); }
+ function close() external { l2Bridge.close(); }
+
+ function registerTokens(address[] memory l1Tokens, address[] memory l2Tokens) public {
+ for (uint256 i; i < l2Tokens.length;) {
+ l2Bridge.registerToken(l1Tokens[i], l2Tokens[i]);
+ AuthLike(l2Tokens[i]).rely(address(l2Bridge));
+ unchecked { ++i; }
+ }
+ }
+
+ function setMaxWithdraws(address[] memory l2Tokens, uint256[] memory maxWithdraws) public {
+ for (uint256 i; i < l2Tokens.length;) {
+ l2Bridge.setMaxWithdraw(l2Tokens[i], maxWithdraws[i]);
+ unchecked { ++i; }
+ }
+ }
+
+ function init(
+ address l2GovRelay_,
+ address l2Bridge_,
+ address l2BridgeImp,
+ address l1GovRelay,
+ address l1Bridge,
+ address l2Messenger,
+ address[] calldata l1Tokens,
+ address[] calldata l2Tokens,
+ uint256[] calldata maxWithdraws
+ ) external {
+ L2GovRelayLike l2GovRelay = L2GovRelayLike(l2GovRelay_);
+
+ // sanity checks
+ require(address(l2Bridge) == l2Bridge_, "L2TokenBridgeSpell/l2-bridge-mismatch");
+ require(keccak256(bytes(l2Bridge.version())) == keccak256("1"), "L2TokenBridgeSpell/version-does-not-match");
+ require(l2Bridge.getImplementation() == l2BridgeImp, "L2TokenBridgeSpell/imp-does-not-match");
+ require(l2Bridge.isOpen() == 1, "L2TokenBridgeSpell/not-open");
+ require(l2Bridge.otherBridge() == l1Bridge, "L2TokenBridgeSpell/other-bridge-mismatch");
+ require(l2Bridge.messenger() == l2Messenger, "L2TokenBridgeSpell/l2-bridge-messenger-mismatch");
+ require(l2GovRelay.l1GovernanceRelay() == l1GovRelay, "L2TokenBridgeSpell/l1-gov-relay-mismatch");
+ require(l2GovRelay.messenger() == l2Messenger, "L2TokenBridgeSpell/l2-gov-relay-messenger-mismatch");
+
+ registerTokens(l1Tokens, l2Tokens);
+ setMaxWithdraws(l2Tokens, maxWithdraws);
+ }
+}
\ No newline at end of file
diff --git a/src/dependencies/base-token-bridge/TokenBridgeInit.sol b/src/dependencies/base-token-bridge/TokenBridgeInit.sol
new file mode 100644
index 000000000..daee06211
--- /dev/null
+++ b/src/dependencies/base-token-bridge/TokenBridgeInit.sol
@@ -0,0 +1,119 @@
+// SPDX-FileCopyrightText: © 2024 Dai Foundation
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.8.0;
+
+import { DssInstance } from "dss-test/MCD.sol";
+import { L1TokenBridgeInstance } from "./L1TokenBridgeInstance.sol";
+import { L2TokenBridgeInstance } from "./L2TokenBridgeInstance.sol";
+import { L2TokenBridgeSpell } from "./L2TokenBridgeSpell.sol";
+
+interface L1TokenBridgeLike {
+ function l1ToL2Token(address) external view returns (address);
+ function isOpen() external view returns (uint256);
+ function otherBridge() external view returns (address);
+ function messenger() external view returns (address);
+ function version() external view returns (string memory);
+ function getImplementation() external view returns (address);
+ function file(bytes32, address) external;
+ function registerToken(address, address) external;
+}
+
+interface L1RelayLike {
+ function l2GovernanceRelay() external view returns (address);
+ function messenger() external view returns (address);
+ function relay(
+ address target,
+ bytes calldata targetData,
+ uint32 minGasLimit
+ ) external;
+}
+
+interface EscrowLike {
+ function approve(address, address, uint256) external;
+}
+
+struct BridgesConfig {
+ address l1Messenger;
+ address l2Messenger;
+ address[] l1Tokens;
+ address[] l2Tokens;
+ uint256[] maxWithdraws;
+ uint32 minGasLimit;
+ bytes32 govRelayCLKey;
+ bytes32 escrowCLKey;
+ bytes32 l1BridgeCLKey;
+ bytes32 l1BridgeImpCLKey;
+}
+
+library TokenBridgeInit {
+ function initBridges(
+ DssInstance memory dss,
+ L1TokenBridgeInstance memory l1BridgeInstance,
+ L2TokenBridgeInstance memory l2BridgeInstance,
+ BridgesConfig memory cfg
+ ) internal {
+ L1RelayLike l1GovRelay = L1RelayLike(l1BridgeInstance.govRelay);
+ EscrowLike escrow = EscrowLike(l1BridgeInstance.escrow);
+ L1TokenBridgeLike l1Bridge = L1TokenBridgeLike(l1BridgeInstance.bridge);
+
+ // sanity checks
+ require(keccak256(bytes(l1Bridge.version())) == keccak256("1"), "TokenBridgeInit/version-does-not-match");
+ require(l1Bridge.getImplementation() == l1BridgeInstance.bridgeImp, "TokenBridgeInit/imp-does-not-match");
+ require(l1Bridge.isOpen() == 1, "TokenBridgeInit/not-open");
+ require(l1Bridge.otherBridge() == l2BridgeInstance.bridge, "TokenBridgeInit/other-bridge-mismatch");
+ require(l1Bridge.messenger() == cfg.l1Messenger, "TokenBridgeInit/l1-bridge-messenger-mismatch");
+ require(l1GovRelay.l2GovernanceRelay() == l2BridgeInstance.govRelay, "TokenBridgeInit/l2-gov-relay-mismatch");
+ require(l1GovRelay.messenger() == cfg.l1Messenger, "TokenBridgeInit/l1-gov-relay-messenger-mismatch");
+ require(cfg.l1Tokens.length == cfg.l2Tokens.length, "TokenBridgeInit/token-arrays-mismatch");
+ require(cfg.maxWithdraws.length == cfg.l2Tokens.length, "TokenBridgeInit/max-withdraws-length-mismatch");
+ require(cfg.minGasLimit <= 1_000_000_000, "TokenBridgeInit/min-gas-limit-out-of-bounds");
+
+ l1Bridge.file("escrow", address(escrow));
+
+ for (uint256 i; i < cfg.l1Tokens.length; ++i) {
+ (address l1Token, address l2Token) = (cfg.l1Tokens[i], cfg.l2Tokens[i]);
+ require(l1Token != address(0), "TokenBridgeInit/invalid-l1-token");
+ require(l2Token != address(0), "TokenBridgeInit/invalid-l2-token");
+ require(cfg.maxWithdraws[i] > 0, "TokenBridgeInit/max-withdraw-not-set");
+ require(l1Bridge.l1ToL2Token(l1Token) == address(0), "TokenBridgeInit/existing-l1-token");
+
+ l1Bridge.registerToken(l1Token, l2Token);
+ escrow.approve(l1Token, address(l1Bridge), type(uint256).max);
+ }
+
+ l1GovRelay.relay({
+ target: l2BridgeInstance.spell,
+ targetData: abi.encodeCall(L2TokenBridgeSpell.init, (
+ l2BridgeInstance.govRelay,
+ l2BridgeInstance.bridge,
+ l2BridgeInstance.bridgeImp,
+ address(l1GovRelay),
+ address(l1Bridge),
+ cfg.l2Messenger,
+ cfg.l1Tokens,
+ cfg.l2Tokens,
+ cfg.maxWithdraws
+ )),
+ minGasLimit: cfg.minGasLimit
+ });
+
+ dss.chainlog.setAddress(cfg.govRelayCLKey, address(l1GovRelay));
+ dss.chainlog.setAddress(cfg.escrowCLKey, address(escrow));
+ dss.chainlog.setAddress(cfg.l1BridgeCLKey, address(l1Bridge));
+ dss.chainlog.setAddress(cfg.l1BridgeImpCLKey, l1BridgeInstance.bridgeImp);
+ }
+}
\ No newline at end of file
diff --git a/src/dependencies/dss-allocator/AllocatorInit.sol b/src/dependencies/dss-allocator/AllocatorInit.sol
new file mode 100644
index 000000000..b87d42ec1
--- /dev/null
+++ b/src/dependencies/dss-allocator/AllocatorInit.sol
@@ -0,0 +1,165 @@
+// SPDX-FileCopyrightText: © 2023 Dai Foundation
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+pragma solidity >=0.8.0;
+
+import { ScriptTools } from "dss-test/ScriptTools.sol";
+import { DssInstance } from "dss-test/MCD.sol";
+import { AllocatorSharedInstance, AllocatorIlkInstance } from "./AllocatorInstances.sol";
+
+interface IlkRegistryLike {
+ function put(
+ bytes32 _ilk,
+ address _join,
+ address _gem,
+ uint256 _dec,
+ uint256 _class,
+ address _pip,
+ address _xlip,
+ string calldata _name,
+ string calldata _symbol
+ ) external;
+}
+
+interface RolesLike {
+ function setIlkAdmin(bytes32, address) external;
+}
+
+interface RegistryLike {
+ function file(bytes32, bytes32, address) external;
+}
+
+interface VaultLike {
+ function ilk() external view returns (bytes32);
+ function roles() external view returns (address);
+ function buffer() external view returns (address);
+ function vat() external view returns (address);
+ function usds() external view returns (address);
+ function file(bytes32, address) external;
+}
+
+interface BufferLike {
+ function approve(address, address, uint256) external;
+}
+
+interface AutoLineLike {
+ function setIlk(bytes32, uint256, uint256, uint256) external;
+}
+
+struct AllocatorIlkConfig {
+ bytes32 ilk;
+ uint256 duty;
+ uint256 gap;
+ uint256 maxLine;
+ uint256 ttl;
+ address allocatorProxy;
+ address ilkRegistry;
+}
+
+function bytes32ToStr(bytes32 _bytes32) pure returns (string memory) {
+ uint256 len;
+ while(len < 32 && _bytes32[len] != 0) len++;
+ bytes memory bytesArray = new bytes(len);
+ for (uint256 i; i < len; i++) {
+ bytesArray[i] = _bytes32[i];
+ }
+ return string(bytesArray);
+}
+
+library AllocatorInit {
+ uint256 constant WAD = 10 ** 18;
+ uint256 constant RAY = 10 ** 27;
+
+ uint256 constant RATES_ONE_HUNDRED_PCT = 1000000021979553151239153027;
+
+ function initShared(
+ DssInstance memory dss,
+ AllocatorSharedInstance memory sharedInstance
+ ) internal {
+ dss.chainlog.setAddress("ALLOCATOR_ROLES", sharedInstance.roles);
+ dss.chainlog.setAddress("ALLOCATOR_REGISTRY", sharedInstance.registry);
+ }
+
+ // Please note this should be executed by the pause proxy
+ function initIlk(
+ DssInstance memory dss,
+ AllocatorSharedInstance memory sharedInstance,
+ AllocatorIlkInstance memory ilkInstance,
+ AllocatorIlkConfig memory cfg
+ ) internal {
+ bytes32 ilk = cfg.ilk;
+
+ // Sanity checks
+ require(VaultLike(ilkInstance.vault).ilk() == ilk, "AllocatorInit/vault-ilk-mismatch");
+ require(VaultLike(ilkInstance.vault).roles() == sharedInstance.roles, "AllocatorInit/vault-roles-mismatch");
+ require(VaultLike(ilkInstance.vault).buffer() == ilkInstance.buffer, "AllocatorInit/vault-buffer-mismatch");
+ require(VaultLike(ilkInstance.vault).vat() == address(dss.vat), "AllocatorInit/vault-vat-mismatch");
+ // Once usdsJoin is in the chainlog and adapted to dss-test should also check against it
+
+ // Onboard the ilk
+ dss.vat.init(ilk);
+ dss.jug.init(ilk);
+
+ require((cfg.duty >= RAY) && (cfg.duty <= RATES_ONE_HUNDRED_PCT), "AllocatorInit/ilk-duty-out-of-bounds");
+ dss.jug.file(ilk, "duty", cfg.duty);
+
+ dss.vat.file(ilk, "line", cfg.gap);
+ dss.vat.file("Line", dss.vat.Line() + cfg.gap);
+ AutoLineLike(dss.chainlog.getAddress("MCD_IAM_AUTO_LINE")).setIlk(ilk, cfg.maxLine, cfg.gap, cfg.ttl);
+
+ dss.spotter.file(ilk, "pip", sharedInstance.oracle);
+ dss.spotter.file(ilk, "mat", RAY);
+ dss.spotter.poke(ilk);
+
+ // Add buffer to registry
+ RegistryLike(sharedInstance.registry).file(ilk, "buffer", ilkInstance.buffer);
+
+ // Initiate the allocator vault
+ dss.vat.slip(ilk, ilkInstance.vault, int256(10**12 * WAD));
+ dss.vat.grab(ilk, ilkInstance.vault, ilkInstance.vault, address(0), int256(10**12 * WAD), 0);
+
+ VaultLike(ilkInstance.vault).file("jug", address(dss.jug));
+
+ // Allow vault to pull funds from the buffer
+ BufferLike(ilkInstance.buffer).approve(VaultLike(ilkInstance.vault).usds(), ilkInstance.vault, type(uint256).max);
+
+ // Set the allocator proxy as the ilk admin instead of the Pause Proxy
+ RolesLike(sharedInstance.roles).setIlkAdmin(ilk, cfg.allocatorProxy);
+
+ // Move ownership of the ilk contracts to the allocator proxy
+ ScriptTools.switchOwner(ilkInstance.vault, ilkInstance.owner, cfg.allocatorProxy);
+ ScriptTools.switchOwner(ilkInstance.buffer, ilkInstance.owner, cfg.allocatorProxy);
+
+ // Add allocator-specific contracts to changelog
+ string memory ilkString = ScriptTools.ilkToChainlogFormat(ilk);
+ dss.chainlog.setAddress(ScriptTools.stringToBytes32(string(abi.encodePacked(ilkString, "_VAULT"))), ilkInstance.vault);
+ dss.chainlog.setAddress(ScriptTools.stringToBytes32(string(abi.encodePacked(ilkString, "_BUFFER"))), ilkInstance.buffer);
+ dss.chainlog.setAddress(ScriptTools.stringToBytes32(string(abi.encodePacked("PIP_", ilkString))), sharedInstance.oracle);
+
+ // Add to ilk registry
+ IlkRegistryLike(cfg.ilkRegistry).put({
+ _ilk : ilk,
+ _join : address(0),
+ _gem : address(0),
+ _dec : 0,
+ _class : 5, // RWAs are class 3, D3Ms and Teleport are class 4
+ _pip : sharedInstance.oracle,
+ _xlip : address(0),
+ _name : bytes32ToStr(ilk),
+ _symbol : bytes32ToStr(ilk)
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/dependencies/dss-flappers/SplitterInstance.sol b/src/dependencies/dss-allocator/AllocatorInstances.sol
similarity index 81%
rename from src/dependencies/dss-flappers/SplitterInstance.sol
rename to src/dependencies/dss-allocator/AllocatorInstances.sol
index bb61fb721..d70193e5d 100644
--- a/src/dependencies/dss-flappers/SplitterInstance.sol
+++ b/src/dependencies/dss-allocator/AllocatorInstances.sol
@@ -16,7 +16,14 @@
pragma solidity >=0.8.0;
-struct SplitterInstance {
- address splitter;
- address mom;
+struct AllocatorSharedInstance {
+ address oracle;
+ address roles;
+ address registry;
}
+
+struct AllocatorIlkInstance {
+ address owner;
+ address vault;
+ address buffer;
+}
\ No newline at end of file
diff --git a/src/dependencies/dss-flappers/FlapperInit.sol b/src/dependencies/dss-flappers/FlapperInit.sol
deleted file mode 100644
index 4d7475efe..000000000
--- a/src/dependencies/dss-flappers/FlapperInit.sol
+++ /dev/null
@@ -1,211 +0,0 @@
-// SPDX-FileCopyrightText: © 2023 Dai Foundation
-// SPDX-License-Identifier: AGPL-3.0-or-later
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-pragma solidity >=0.8.0;
-
-import { DssInstance } from "dss-test/MCD.sol";
-import { SplitterInstance } from "./SplitterInstance.sol";
-
-interface FlapperUniV2Like {
- function pip() external view returns (address);
- function spotter() external view returns (address);
- function usds() external view returns (address);
- function gem() external view returns (address);
- function receiver() external view returns (address);
- function pair() external view returns (address);
- function rely(address) external;
- function file(bytes32, uint256) external;
- function file(bytes32, address) external;
-}
-
-interface SplitterMomLike {
- function splitter() external view returns (address);
- function setAuthority(address) external;
-}
-
-interface OracleWrapperLike {
- function pip() external view returns (address);
- function divisor() external view returns (uint256);
-}
-
-interface PipLike {
- function kiss(address) external;
-}
-
-interface PairLike {
- function token0() external view returns (address);
- function token1() external view returns (address);
-}
-
-interface UsdsJoinLike {
- function dai() external view returns (address); // TODO: Replace when new join is ready by the new getter
-}
-
-interface SplitterLike {
- function live() external view returns (uint256);
- function vat() external view returns (address);
- function usdsJoin() external view returns (address);
- function hop() external view returns (uint256);
- function rely(address) external;
- function file(bytes32, uint256) external;
- function file(bytes32, address) external;
-}
-
-interface FarmLike {
- function rewardsToken() external view returns (address);
- function setRewardsDistribution(address) external;
- function setRewardsDuration(uint256) external;
-}
-
-struct FlapperUniV2Config {
- uint256 want;
- address pip;
- address pair;
- address usds;
- address splitter;
- bytes32 prevChainlogKey;
- bytes32 chainlogKey;
-}
-
-struct FarmConfig {
- address splitter;
- address usdsJoin;
- uint256 hop;
- bytes32 prevChainlogKey;
- bytes32 chainlogKey;
-}
-
-struct SplitterConfig {
- uint256 hump;
- uint256 bump;
- uint256 hop;
- uint256 burn;
- address usdsJoin;
- bytes32 splitterChainlogKey;
- bytes32 prevMomChainlogKey;
- bytes32 momChainlogKey;
-}
-
-library FlapperInit {
- uint256 constant WAD = 10 ** 18;
- uint256 constant RAY = 10 ** 27;
-
- function initFlapperUniV2(
- DssInstance memory dss,
- address flapper_,
- FlapperUniV2Config memory cfg
- ) internal {
- FlapperUniV2Like flapper = FlapperUniV2Like(flapper_);
-
- // Sanity checks
- require(flapper.spotter() == address(dss.spotter), "Flapper spotter mismatch");
- require(flapper.usds() == cfg.usds, "Flapper usds mismatch");
- require(flapper.pair() == cfg.pair, "Flapper pair mismatch");
- require(flapper.receiver() == dss.chainlog.getAddress("MCD_PAUSE_PROXY"), "Flapper receiver mismatch");
-
- PairLike pair = PairLike(flapper.pair());
- (address pairUsds, address pairGem) = pair.token0() == cfg.usds ? (pair.token0(), pair.token1())
- : (pair.token1(), pair.token0());
- require(pairUsds == cfg.usds, "Usds mismatch");
- require(pairGem == flapper.gem(), "Gem mismatch");
-
- require(cfg.want >= WAD * 90 / 100, "want too low");
-
- flapper.file("want", cfg.want);
- flapper.file("pip", cfg.pip);
- flapper.rely(cfg.splitter);
-
- SplitterLike(cfg.splitter).file("flapper", flapper_);
-
- if (cfg.prevChainlogKey != bytes32(0)) dss.chainlog.removeAddress(cfg.prevChainlogKey);
- dss.chainlog.setAddress(cfg.chainlogKey, flapper_);
- }
-
- function initDirectOracle(address flapper) internal {
- PipLike(FlapperUniV2Like(flapper).pip()).kiss(flapper);
- }
-
- function initOracleWrapper(
- DssInstance memory dss,
- address wrapper_,
- uint256 divisor,
- bytes32 clKey
- ) internal {
- OracleWrapperLike wrapper = OracleWrapperLike(wrapper_);
- require(wrapper.divisor() == divisor, "Wrapper divisor mismatch"); // Sanity check
- PipLike(wrapper.pip()).kiss(wrapper_);
- dss.chainlog.setAddress(clKey, wrapper_);
- }
-
- function setFarm(
- DssInstance memory dss,
- address farm_,
- FarmConfig memory cfg
- ) internal {
- FarmLike farm = FarmLike(farm_);
- SplitterLike splitter = SplitterLike(cfg.splitter);
-
- require(farm.rewardsToken() == UsdsJoinLike(cfg.usdsJoin).dai(), "Farm rewards not usds");
- // Staking token is checked in the Lockstake script
-
- // The following two checks enforce the initSplitter function has to be called first
- require(cfg.hop >= 5 minutes, "hop too low");
- require(cfg.hop == splitter.hop(), "hop mismatch");
-
- splitter.file("farm", farm_);
-
- farm.setRewardsDistribution(cfg.splitter);
- farm.setRewardsDuration(cfg.hop);
-
- if (cfg.prevChainlogKey != bytes32(0)) dss.chainlog.removeAddress(cfg.prevChainlogKey);
- dss.chainlog.setAddress(cfg.chainlogKey, farm_);
- }
-
- function initSplitter(
- DssInstance memory dss,
- SplitterInstance memory splitterInstance,
- SplitterConfig memory cfg
- ) internal {
- SplitterLike splitter = SplitterLike(splitterInstance.splitter);
- SplitterMomLike mom = SplitterMomLike(splitterInstance.mom);
-
- // Sanity checks
- require(splitter.live() == 1, "Splitter not live");
- require(splitter.vat() == address(dss.vat), "Splitter vat mismatch");
- require(splitter.usdsJoin() == cfg.usdsJoin, "Splitter usdsJoin mismatch");
- require(mom.splitter() == splitterInstance.splitter, "Mom splitter mismatch");
-
- require(cfg.hump > 0, "hump too low");
- require(cfg.bump % RAY == 0, "bump not multiple of RAY");
- require(cfg.hop >= 5 minutes, "hop too low");
- require(cfg.burn <= WAD, "burn too high");
-
- splitter.file("hop", cfg.hop);
- splitter.file("burn", cfg.burn);
- splitter.rely(address(mom));
- splitter.rely(address(dss.vow));
-
- dss.vow.file("flapper", splitterInstance.splitter);
- dss.vow.file("hump", cfg.hump);
- dss.vow.file("bump", cfg.bump);
-
- mom.setAuthority(dss.chainlog.getAddress("MCD_ADM"));
-
- dss.chainlog.setAddress(cfg.splitterChainlogKey, splitterInstance.splitter);
- if (cfg.prevMomChainlogKey != bytes32(0)) dss.chainlog.removeAddress(cfg.prevMomChainlogKey);
- dss.chainlog.setAddress(cfg.momChainlogKey, address(mom));
- }
-}
diff --git a/src/dependencies/lockstake/LockstakeInit.sol b/src/dependencies/lockstake/LockstakeInit.sol
deleted file mode 100644
index 57809d25d..000000000
--- a/src/dependencies/lockstake/LockstakeInit.sol
+++ /dev/null
@@ -1,259 +0,0 @@
-// SPDX-FileCopyrightText: © 2023 Dai Foundation
-// SPDX-License-Identifier: AGPL-3.0-or-later
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-
-pragma solidity >=0.8.0;
-
-import { DssInstance } from "dss-test/MCD.sol";
-import { LockstakeInstance } from "./LockstakeInstance.sol";
-
-interface LockstakeMkrLike {
- function rely(address) external;
-}
-
-interface LockstakeEngineLike {
- function voteDelegateFactory() external view returns (address);
- function vat() external view returns (address);
- function usdsJoin() external view returns (address);
- function usds() external view returns (address);
- function ilk() external view returns (bytes32);
- function mkr() external view returns (address);
- function lsmkr() external view returns (address);
- function fee() external view returns (uint256);
- function mkrSky() external view returns (address);
- function sky() external view returns (address);
- function rely(address) external;
- function file(bytes32, address) external;
- function file(bytes32, uint256) external;
- function addFarm(address) external;
-}
-
-interface LockstakeClipperLike {
- function vat() external view returns (address);
- function dog() external view returns (address);
- function spotter() external view returns (address);
- function engine() external view returns (address);
- function ilk() external view returns (bytes32);
- function rely(address) external;
- function file(bytes32, address) external;
- function file(bytes32, uint256) external;
- function upchost() external;
-}
-
-interface PipLike {
- function kiss(address) external;
- function rely(address) external;
-}
-
-interface CalcLike {
- function file(bytes32, uint256) external;
-}
-
-interface AutoLineLike {
- function setIlk(bytes32, uint256, uint256, uint256) external;
-}
-
-interface OsmMomLike {
- function setOsm(bytes32, address) external;
-}
-
-interface LineMomLike {
- function addIlk(bytes32) external;
-}
-
-interface ClipperMomLike {
- function setPriceTolerance(address, uint256) external;
-}
-
-interface StakingRewardsLike {
- function stakingToken() external view returns (address);
-}
-
-interface IlkRegistryLike {
- function put(
- bytes32 _ilk,
- address _join,
- address _gem,
- uint256 _dec,
- uint256 _class,
- address _pip,
- address _xlip,
- string memory _name,
- string memory _symbol
- ) external;
-}
-
-struct LockstakeConfig {
- bytes32 ilk;
- address voteDelegateFactory;
- address usdsJoin;
- address usds;
- address mkr;
- address mkrSky;
- address sky;
- address[] farms;
- uint256 fee;
- uint256 maxLine;
- uint256 gap;
- uint256 ttl;
- uint256 dust;
- uint256 duty;
- uint256 mat;
- uint256 buf;
- uint256 tail;
- uint256 cusp;
- uint256 chip;
- uint256 tip;
- uint256 stopped;
- uint256 chop;
- uint256 hole;
- uint256 tau;
- uint256 cut;
- uint256 step;
- bool lineMom;
- uint256 tolerance;
- string name;
- string symbol;
-}
-
-library LockstakeInit {
- uint256 constant internal RATES_ONE_HUNDRED_PCT = 1000000021979553151239153027;
- uint256 constant internal WAD = 10**18;
- uint256 constant internal RAY = 10**27;
- uint256 constant internal RAD = 10**45;
-
- function initLockstake(
- DssInstance memory dss,
- LockstakeInstance memory lockstakeInstance,
- LockstakeConfig memory cfg
- ) internal {
- LockstakeEngineLike engine = LockstakeEngineLike(lockstakeInstance.engine);
- LockstakeClipperLike clipper = LockstakeClipperLike(lockstakeInstance.clipper);
- CalcLike calc = CalcLike(lockstakeInstance.clipperCalc);
-
- // Sanity checks
- require(engine.voteDelegateFactory() == cfg.voteDelegateFactory, "Engine voteDelegateFactory mismatch");
- require(engine.vat() == address(dss.vat), "Engine vat mismatch");
- require(engine.usdsJoin() == cfg.usdsJoin, "Engine usdsJoin mismatch");
- require(engine.usds() == cfg.usds, "Engine usds mismatch");
- require(engine.ilk() == cfg.ilk, "Engine ilk mismatch");
- require(engine.mkr() == cfg.mkr, "Engine mkr mismatch");
- require(engine.lsmkr() == lockstakeInstance.lsmkr, "Engine lsmkr mismatch");
- require(engine.mkrSky() == cfg.mkrSky, "Engine mkrSky mismatch");
- require(engine.sky() == cfg.sky, "Engine sky mismatch");
- require(clipper.ilk() == cfg.ilk, "Clipper ilk mismatch");
- require(clipper.vat() == address(dss.vat), "Clipper vat mismatch");
- require(clipper.engine() == address(engine), "Clipper engine mismatch");
- require(clipper.dog() == address(dss.dog), "Clipper dog mismatch");
- require(clipper.spotter() == address(dss.spotter), "Clipper spotter mismatch");
-
- require(cfg.gap <= cfg.maxLine, "gap greater than max line");
- require(cfg.dust <= cfg.hole, "dust greater than hole");
- require(cfg.duty >= RAY && cfg.duty <= RATES_ONE_HUNDRED_PCT, "duty out of boundaries");
- require(cfg.mat >= RAY && cfg.mat < 10 * RAY, "mat out of boundaries");
- require(cfg.buf >= RAY && cfg.buf < 10 * RAY, "buf out of boundaries");
- require(cfg.cusp < RAY, "cusp negative drop value");
- require(cfg.chip < WAD, "chip equal or greater than 100%");
- require(cfg.tip <= 1_000 * RAD, "tip out of boundaries");
- require(cfg.chop >= WAD && cfg.chop < 2 * WAD, "chop out of boundaries");
- require(cfg.tolerance < RAY, "tolerance equal or greater than 100%");
-
- dss.vat.init(cfg.ilk);
- dss.vat.file(cfg.ilk, "line", cfg.gap);
- dss.vat.file("Line", dss.vat.Line() + cfg.gap);
- dss.vat.file(cfg.ilk, "dust", cfg.dust);
- dss.vat.rely(address(engine));
- dss.vat.rely(address(clipper));
-
- AutoLineLike(dss.chainlog.getAddress("MCD_IAM_AUTO_LINE")).setIlk(cfg.ilk, cfg.maxLine, cfg.gap, cfg.ttl);
-
- dss.jug.init(cfg.ilk);
- dss.jug.file(cfg.ilk, "duty", cfg.duty);
-
- address pip = dss.chainlog.getAddress("PIP_MKR");
- address clipperMom = dss.chainlog.getAddress("CLIPPER_MOM");
- PipLike(pip).kiss(address(dss.spotter));
- PipLike(pip).kiss(address(clipper));
- PipLike(pip).kiss(clipperMom);
- PipLike(pip).kiss(address(dss.end));
- // This assumes pip is a standard Osm sourced by a Median
- {
- address osmMom = dss.chainlog.getAddress("OSM_MOM");
- PipLike(pip).rely(osmMom);
- OsmMomLike(osmMom).setOsm(cfg.ilk, pip);
- }
-
- dss.spotter.file(cfg.ilk, "mat", cfg.mat);
- dss.spotter.file(cfg.ilk, "pip", pip);
- dss.spotter.poke(cfg.ilk);
-
- dss.dog.file(cfg.ilk, "clip", address(clipper));
- dss.dog.file(cfg.ilk, "chop", cfg.chop);
- dss.dog.file(cfg.ilk, "hole", cfg.hole);
- dss.dog.rely(address(clipper));
-
- LockstakeMkrLike(lockstakeInstance.lsmkr).rely(address(engine));
-
- engine.file("jug", address(dss.jug));
- engine.file("fee", cfg.fee);
- for (uint256 i = 0; i < cfg.farms.length; i++) {
- require(StakingRewardsLike(cfg.farms[i]).stakingToken() == lockstakeInstance.lsmkr, "Farm staking token mismatch");
- engine.addFarm(cfg.farms[i]);
- }
- engine.rely(address(clipper));
-
- clipper.file("buf", cfg.buf);
- clipper.file("tail", cfg.tail);
- clipper.file("cusp", cfg.cusp);
- clipper.file("chip", cfg.chip);
- clipper.file("tip", cfg.tip);
- clipper.file("stopped", cfg.stopped);
- clipper.file("vow", address(dss.vow));
- clipper.file("calc", address(calc));
- clipper.upchost();
- clipper.rely(address(dss.dog));
- clipper.rely(address(dss.end));
- clipper.rely(clipperMom);
-
- if (cfg.tau > 0) calc.file("tau", cfg.tau);
- if (cfg.cut > 0) calc.file("cut", cfg.cut);
- if (cfg.step > 0) calc.file("step", cfg.step);
-
- if (cfg.lineMom) {
- LineMomLike(dss.chainlog.getAddress("LINE_MOM")).addIlk(cfg.ilk);
- }
-
- if (cfg.tolerance > 0) {
- ClipperMomLike(clipperMom).setPriceTolerance(address(clipper), cfg.tolerance);
- }
-
- IlkRegistryLike(dss.chainlog.getAddress("ILK_REGISTRY")).put(
- cfg.ilk,
- address(0),
- cfg.mkr,
- 18,
- 7, // New class
- pip,
- address(clipper),
- cfg.name,
- cfg.symbol
- );
-
- dss.chainlog.setAddress("LOCKSTAKE_MKR", lockstakeInstance.lsmkr);
- dss.chainlog.setAddress("LOCKSTAKE_ENGINE", address(engine));
- dss.chainlog.setAddress("LOCKSTAKE_CLIP", address(clipper));
- dss.chainlog.setAddress("LOCKSTAKE_CLIP_CALC", address(calc));
- }
-}
diff --git a/src/test/addresses_mainnet.sol b/src/test/addresses_mainnet.sol
index 87f3bb6bd..d428f4deb 100644
--- a/src/test/addresses_mainnet.sol
+++ b/src/test/addresses_mainnet.sol
@@ -518,5 +518,14 @@ contract Addresses {
addr["LOCKSTAKE_ENGINE"] = 0x2b16C07D5fD5cC701a0a871eae2aad6DA5fc8f12;
addr["LOCKSTAKE_CLIP"] = 0xA85621D35cAf9Cf5C146D2376Ce553D7B78A6239;
addr["LOCKSTAKE_CLIP_CALC"] = 0xf13cF3b39823CcfaE6C2354dA56416C80768474e;
+ addr["BASE_GOV_RELAY"] = 0x1Ee0AE8A993F2f5abDB51EAF4AC2876202b65c3b;
+ addr["BASE_ESCROW"] = 0x7F311a4D48377030bD810395f4CCfC03bdbe9Ef3;
+ addr["BASE_TOKEN_BRIDGE"] = 0xA5874756416Fa632257eEA380CAbd2E87cED352A;
+ addr["BASE_TOKEN_BRIDGE_IMP"] = 0xaeFd31c2e593Dc971f9Cb42cBbD5d4AD7F1970b6;
+ addr["ALLOCATOR_ROLES"] = 0x9A865A710399cea85dbD9144b7a09C889e94E803;
+ addr["ALLOCATOR_REGISTRY"] = 0xCdCFA95343DA7821fdD01dc4d0AeDA958051bB3B;
+ addr["ALLOCATOR_SPARK_A_VAULT"] = 0x691a6c29e9e96dd897718305427Ad5D534db16BA;
+ addr["ALLOCATOR_SPARK_A_BUFFER"] = 0xc395D150e71378B47A1b8E9de0c1a83b75a08324;
+ addr["PIP_ALLOCATOR_SPARK_A"] = 0xc7B91C401C02B73CBdF424dFaaa60950d5040dB7;
}
}
diff --git a/src/test/config.sol b/src/test/config.sol
index d43259025..55f6aecbe 100644
--- a/src/test/config.sol
+++ b/src/test/config.sol
@@ -104,9 +104,9 @@ contract Config {
// Values for spell-specific parameters
//
spellValues = SpellValues({
- deployed_spell: address(0xACA9a90C92647e3d3f04095118192DC80C470955), // populate with deployed spell if deployed
- deployed_spell_created: 1729197815, // use `make deploy-info tx=` to obtain the timestamp
- deployed_spell_block: 20987749, // use `make deploy-info tx=` to obtain the block number
+ deployed_spell: address(0), // populate with deployed spell if deployed
+ deployed_spell_created: 0, // use `make deploy-info tx=` to obtain the timestamp
+ deployed_spell_block: 0, // use `make deploy-info tx=` to obtain the block number
previous_spells: prevSpells, // older spells to ensure are executed first
office_hours_enabled: true, // true if officehours is expected to be enabled in the spell
expiration_threshold: 30 days // Amount of time before spell expires
@@ -142,8 +142,8 @@ contract Config {
afterSpell.vest_mkr_cap = 2_220 * WAD / 365 days; // In WAD MKR per second
afterSpell.vest_sky_cap = 800 * MILLION * WAD / 365 days; // In WAD SKY per second
afterSpell.sky_mkr_rate = 24_000; // In whole SKY/MKR units
- afterSpell.ilk_count = 68; // Num expected in system
- afterSpell.chainlog_version = "1.19.2"; // String expected in system
+ afterSpell.ilk_count = 69; // Num expected in system
+ afterSpell.chainlog_version = "1.19.3"; // String expected in system
//
// Values for all collateral
@@ -1849,5 +1849,30 @@ contract Config {
calc_cut: 99_00,
offboarding: false
});
+ afterSpell.collaterals["ALLOCATOR-SPARK-A"] = CollateralValues({
+ aL_enabled: true,
+ aL_line: 10 * MILLION,
+ aL_gap: 2_500_000,
+ aL_ttl: 24 hours,
+ line: 0,
+ dust: 0,
+ pct: 520,
+ mat: 10000,
+ liqType: "",
+ liqOn: false,
+ chop: 0,
+ dog_hole: 0,
+ clip_buf: 0,
+ clip_tail: 0,
+ clip_cusp: 0,
+ clip_chip: 0,
+ clip_tip: 0,
+ clipper_mom: 0,
+ cm_tolerance: 0,
+ calc_tau: 0,
+ calc_step: 0,
+ calc_cut: 0,
+ offboarding: false
+ });
}
}
diff --git a/src/test/rates.sol b/src/test/rates.sol
index 3d20b1e22..79d1f8d1b 100644
--- a/src/test/rates.sol
+++ b/src/test/rates.sol
@@ -60,6 +60,7 @@ contract Rates {
rates[ 475] = 1000000001471536429740616381;
rates[ 490] = 1000000001516911765932351183;
rates[ 500] = 1000000001547125957863212448;
+ rates[ 520] = 1000000001607468111246255079;
rates[ 525] = 1000000001622535724756171269;
rates[ 544] = 1000000001679727448331902751;
rates[ 550] = 1000000001697766583380253701;