Skip to content

Commit 7e74204

Browse files
feat: Frontier PTs on Plasma
1 parent db5790e commit 7e74204

File tree

12 files changed

+602
-0
lines changed

12 files changed

+602
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"externalVaults": [],
3+
"irms": [
4+
"0x0000000000000000000000000000000000000000",
5+
"0xf41D1f354f04A2887682ba3585Bf6cCca0a24551",
6+
"0xf41D1f354f04A2887682ba3585Bf6cCca0a24551"
7+
],
8+
"oracleRouters": [
9+
"0xc3c183966ec256258A4c8F8C025A3fc8502a25C9",
10+
"0xc3c183966ec256258A4c8F8C025A3fc8502a25C9",
11+
"0xc3c183966ec256258A4c8F8C025A3fc8502a25C9"
12+
],
13+
"stubOracle": "0x0000000000000000000000000000000000000000",
14+
"vaults": [
15+
"0x75C4D639067ddAf77f6BEc440e68DDdFab2C47eE",
16+
"0x35b6f39affA0020c1736cdC764287bfd32Ee4324",
17+
"0x0D10591241F67449102ACF05CD9c480CfE43154c"
18+
]
19+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
pragma solidity ^0.8.0;
4+
5+
import {Ownable} from "openzeppelin-contracts/access/Ownable.sol";
6+
import {ManageCluster} from "./ManageCluster.s.sol";
7+
import {OracleVerifier} from "../../../utils/SanityCheckOracle.s.sol";
8+
9+
contract Cluster is ManageCluster {
10+
function defineCluster() internal override {
11+
// define the path to the cluster addresses file here
12+
cluster.clusterAddressesPath = "/script/production/plasma/clusters/M12PT-USDe.json";
13+
14+
// do not change the order of the assets in the .assets array. if done, it must be reflected in other the other arrays the ltvs matrix.
15+
// if more than one vauls has to be deployed for the same asset, it can be added in the array as many times as needed.
16+
// note however, that mappings may need reworking as they always use asset address as key.
17+
cluster.assets = [
18+
PT_USDe_15JAN2026,
19+
USDe,
20+
USDT0
21+
];
22+
}
23+
24+
function configureCluster() internal override {
25+
// define the governors here
26+
cluster.oracleRoutersGovernor = cluster.vaultsGovernor = governorAddresses.accessControlEmergencyGovernor;
27+
28+
// define unit of account here
29+
cluster.unitOfAccount = USD;
30+
31+
// define fee receiver here and interest fee here. if needed to be defined per asset, populate the feeReceiverOverride and interestFeeOverride mappings
32+
cluster.feeReceiver = address(0);
33+
cluster.interestFee = 0.1e4;
34+
35+
// define max liquidation discount here. if needed to be defined per asset, populate the maxLiquidationDiscountOverride mapping
36+
cluster.maxLiquidationDiscount = 0.15e4;
37+
38+
// define liquidation cool off time here. if needed to be defined per asset, populate the liquidationCoolOffTimeOverride mapping
39+
cluster.liquidationCoolOffTime = 1;
40+
41+
// define hook target and hooked ops here. if needed to be defined per asset, populate the hookTargetOverride and hookedOpsOverride mappings
42+
cluster.hookTarget = address(0);
43+
cluster.hookedOps = 0;
44+
45+
// define config flags here. if needed to be defined per asset, populate the configFlagsOverride mapping
46+
cluster.configFlags = 0;
47+
48+
// define oracle providers here.
49+
// adapter names can be found in the relevant adapter contract (as returned by the `name` function).
50+
// for cross adapters, use the following format: "CrossAdapter=<adapterName1>+<adapterName2>".
51+
// although Redstone Classic oracles reuse the ChainlinkOracle contract and returns "ChainlinkOracle" name,
52+
// they should be referred to as "RedstoneClassicOracle".
53+
// in case the asset is an ERC4626 vault itself (i.e. sUSDS) and is recognized as a valid external vault as per
54+
// External Vaults Registry, the string should be preceeded by "ExternalVault|" prefix. this is in order to resolve
55+
// the asset (vault) in the oracle router.
56+
// in case the adapter is not present in the Adapter Registry, the adapter address can be passed instead in form of a string.
57+
cluster.oracleProviders[PT_USDe_15JAN2026] = "0x6106d4DC3A2Ea3cCeF9CdaBD1B57a71843F7d9E3";
58+
cluster.oracleProviders[USDe] = "0x59E8BD99802F4EB774dFfE2BE2bEC38Ad08d6c16";
59+
cluster.oracleProviders[USDT0] = "0xE8947CFd3f04E686741F7Dd9023ec0C78588fd33";
60+
61+
// define supply caps here. 0 means no supply can occur, type(uint256).max means no cap defined hence max amount
62+
cluster.supplyCaps[PT_USDe_15JAN2026] = type(uint256).max;
63+
cluster.supplyCaps[USDe] = type(uint256).max;
64+
cluster.supplyCaps[USDT0] = type(uint256).max;
65+
66+
// define borrow caps here. 0 means no borrow can occur, type(uint256).max means no cap defined hence max amount
67+
cluster.borrowCaps[PT_USDe_15JAN2026] = type(uint256).max;
68+
cluster.borrowCaps[USDe] = type(uint256).max;
69+
cluster.borrowCaps[USDT0] = type(uint256).max;
70+
71+
// define IRM classes here and assign them to the assets
72+
cluster.irms[USDe ] = IRM_ADAPTIVE_USD;
73+
cluster.irms[USDT0] = IRM_ADAPTIVE_USD;
74+
75+
// define the ramp duration to be used, in case the liquidation LTVs have to be ramped down
76+
cluster.rampDuration = 1 days;
77+
78+
// define the spread between borrow and liquidation ltv
79+
cluster.spreadLTV = 0.02e4;
80+
81+
// define ltv values here. columns are liability vaults, rows are collateral vaults
82+
cluster.ltvs = [
83+
// 0 1 2
84+
// PT-USDe USDe USDT0
85+
/* 0 PT-USDe */ [LTV_ZERO, LTV_HIGH, LTV__LOW],
86+
/* 1 USDe */ [LTV_ZERO, LTV_ZERO, LTV_ZERO],
87+
/* 2 USDT0 */ [LTV_ZERO, LTV_ZERO, LTV_ZERO]
88+
];
89+
90+
// define external ltvs here. columns are liability vaults, rows are collateral vaults.
91+
// double check the order of collaterals against the order of externalVaults in the addresses file
92+
}
93+
94+
function postOperations() internal view override {
95+
for (uint256 i = 0; i < cluster.vaults.length; ++i) {
96+
OracleVerifier.verifyOracleConfig(lensAddresses.oracleLens, cluster.vaults[i], false);
97+
}
98+
}
99+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"externalVaults": [],
3+
"irms": [
4+
"0x0000000000000000000000000000000000000000",
5+
"0xf41D1f354f04A2887682ba3585Bf6cCca0a24551",
6+
"0xf41D1f354f04A2887682ba3585Bf6cCca0a24551"
7+
],
8+
"oracleRouters": [
9+
"0x766F16C191d2D0470AcBbc7BE56bBBBb6C1aE52C",
10+
"0x766F16C191d2D0470AcBbc7BE56bBBBb6C1aE52C",
11+
"0x766F16C191d2D0470AcBbc7BE56bBBBb6C1aE52C"
12+
],
13+
"stubOracle": "0x0000000000000000000000000000000000000000",
14+
"vaults": [
15+
"0xc3fF7A69A232239ce306dB50d63Ab2737053e24C",
16+
"0xd9e36ad27AfF5bBF2c65026462d45DF093554D38",
17+
"0x8073b76bBd1B40F1Fb2b6AEf7A920B1914Bb86AB"
18+
]
19+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
pragma solidity ^0.8.0;
4+
5+
import {Ownable} from "openzeppelin-contracts/access/Ownable.sol";
6+
import {ManageCluster} from "./ManageCluster.s.sol";
7+
import {OracleVerifier} from "../../../utils/SanityCheckOracle.s.sol";
8+
9+
contract Cluster is ManageCluster {
10+
function defineCluster() internal override {
11+
// define the path to the cluster addresses file here
12+
cluster.clusterAddressesPath = "/script/production/plasma/clusters/M13PT-sUSDe.json";
13+
14+
// do not change the order of the assets in the .assets array. if done, it must be reflected in other the other arrays the ltvs matrix.
15+
// if more than one vauls has to be deployed for the same asset, it can be added in the array as many times as needed.
16+
// note however, that mappings may need reworking as they always use asset address as key.
17+
cluster.assets = [
18+
PT_sUSDe_15JAN2026,
19+
USDe,
20+
USDT0
21+
];
22+
}
23+
24+
function configureCluster() internal override {
25+
// define the governors here
26+
cluster.oracleRoutersGovernor = cluster.vaultsGovernor = governorAddresses.accessControlEmergencyGovernor;
27+
28+
// define unit of account here
29+
cluster.unitOfAccount = USD;
30+
31+
// define fee receiver here and interest fee here. if needed to be defined per asset, populate the feeReceiverOverride and interestFeeOverride mappings
32+
cluster.feeReceiver = address(0);
33+
cluster.interestFee = 0.1e4;
34+
35+
// define max liquidation discount here. if needed to be defined per asset, populate the maxLiquidationDiscountOverride mapping
36+
cluster.maxLiquidationDiscount = 0.15e4;
37+
38+
// define liquidation cool off time here. if needed to be defined per asset, populate the liquidationCoolOffTimeOverride mapping
39+
cluster.liquidationCoolOffTime = 1;
40+
41+
// define hook target and hooked ops here. if needed to be defined per asset, populate the hookTargetOverride and hookedOpsOverride mappings
42+
cluster.hookTarget = address(0);
43+
cluster.hookedOps = 0;
44+
45+
// define config flags here. if needed to be defined per asset, populate the configFlagsOverride mapping
46+
cluster.configFlags = 0;
47+
48+
// define oracle providers here.
49+
// adapter names can be found in the relevant adapter contract (as returned by the `name` function).
50+
// for cross adapters, use the following format: "CrossAdapter=<adapterName1>+<adapterName2>".
51+
// although Redstone Classic oracles reuse the ChainlinkOracle contract and returns "ChainlinkOracle" name,
52+
// they should be referred to as "RedstoneClassicOracle".
53+
// in case the asset is an ERC4626 vault itself (i.e. sUSDS) and is recognized as a valid external vault as per
54+
// External Vaults Registry, the string should be preceeded by "ExternalVault|" prefix. this is in order to resolve
55+
// the asset (vault) in the oracle router.
56+
// in case the adapter is not present in the Adapter Registry, the adapter address can be passed instead in form of a string.
57+
cluster.oracleProviders[PT_sUSDe_15JAN2026] = "0x8890148A2D8f6e3cEE111FF641CA7Ccd859f5F54";
58+
cluster.oracleProviders[USDe] = "0x59E8BD99802F4EB774dFfE2BE2bEC38Ad08d6c16";
59+
cluster.oracleProviders[USDT0] = "0xE8947CFd3f04E686741F7Dd9023ec0C78588fd33";
60+
61+
// define supply caps here. 0 means no supply can occur, type(uint256).max means no cap defined hence max amount
62+
cluster.supplyCaps[PT_sUSDe_15JAN2026] = type(uint256).max;
63+
cluster.supplyCaps[USDe] = type(uint256).max;
64+
cluster.supplyCaps[USDT0] = type(uint256).max;
65+
66+
// define borrow caps here. 0 means no borrow can occur, type(uint256).max means no cap defined hence max amount
67+
cluster.borrowCaps[PT_sUSDe_15JAN2026] = type(uint256).max;
68+
cluster.borrowCaps[USDe] = type(uint256).max;
69+
cluster.borrowCaps[USDT0] = type(uint256).max;
70+
71+
// define IRM classes here and assign them to the assets
72+
cluster.irms[USDe ] = IRM_ADAPTIVE_USD;
73+
cluster.irms[USDT0] = IRM_ADAPTIVE_USD;
74+
75+
// define the ramp duration to be used, in case the liquidation LTVs have to be ramped down
76+
cluster.rampDuration = 1 days;
77+
78+
// define the spread between borrow and liquidation ltv
79+
cluster.spreadLTV = 0.02e4;
80+
81+
// define ltv values here. columns are liability vaults, rows are collateral vaults
82+
cluster.ltvs = [
83+
// 0 1 2
84+
// PT-sUSDe USDe USDT0
85+
/* 0 PT-sUSDe*/ [LTV_ZERO, LTV_HIGH, LTV__LOW],
86+
/* 1 USDe */ [LTV_ZERO, LTV_ZERO, LTV_ZERO],
87+
/* 2 USDT0 */ [LTV_ZERO, LTV_ZERO, LTV_ZERO]
88+
];
89+
90+
// define external ltvs here. columns are liability vaults, rows are collateral vaults.
91+
// double check the order of collaterals against the order of externalVaults in the addresses file
92+
}
93+
94+
function postOperations() internal view override {
95+
for (uint256 i = 0; i < cluster.vaults.length; ++i) {
96+
OracleVerifier.verifyOracleConfig(lensAddresses.oracleLens, cluster.vaults[i], false);
97+
}
98+
}
99+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"externalVaults": [],
3+
"irms": [
4+
"0x0000000000000000000000000000000000000000",
5+
"0xf41D1f354f04A2887682ba3585Bf6cCca0a24551"
6+
],
7+
"oracleRouters": [
8+
"0xFDf85f60B83E3E6F96098f576C03439b00a05C3f",
9+
"0xFDf85f60B83E3E6F96098f576C03439b00a05C3f"
10+
],
11+
"stubOracle": "0x0000000000000000000000000000000000000000",
12+
"vaults": [
13+
"0x0bB995211462d10495136C6F2eCc367435481c2d",
14+
"0xf0A1bDf7e678144702feC359fa1A0eb50b0B8845"
15+
]
16+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
pragma solidity ^0.8.0;
4+
5+
import {Ownable} from "openzeppelin-contracts/access/Ownable.sol";
6+
import {ManageCluster} from "./ManageCluster.s.sol";
7+
import {OracleVerifier} from "../../../utils/SanityCheckOracle.s.sol";
8+
9+
contract Cluster is ManageCluster {
10+
function defineCluster() internal override {
11+
// define the path to the cluster addresses file here
12+
cluster.clusterAddressesPath = "/script/production/plasma/clusters/M14PT-syrupUSDT.json";
13+
14+
// do not change the order of the assets in the .assets array. if done, it must be reflected in other the other arrays the ltvs matrix.
15+
// if more than one vauls has to be deployed for the same asset, it can be added in the array as many times as needed.
16+
// note however, that mappings may need reworking as they always use asset address as key.
17+
cluster.assets = [
18+
PT_syrupUSDT_29JAN2026,
19+
USDT0
20+
];
21+
}
22+
23+
function configureCluster() internal override {
24+
// define the governors here
25+
cluster.oracleRoutersGovernor = cluster.vaultsGovernor = governorAddresses.accessControlEmergencyGovernor;
26+
27+
// define unit of account here
28+
cluster.unitOfAccount = USD;
29+
30+
// define fee receiver here and interest fee here. if needed to be defined per asset, populate the feeReceiverOverride and interestFeeOverride mappings
31+
cluster.feeReceiver = address(0);
32+
cluster.interestFee = 0.1e4;
33+
34+
// define max liquidation discount here. if needed to be defined per asset, populate the maxLiquidationDiscountOverride mapping
35+
cluster.maxLiquidationDiscount = 0.15e4;
36+
37+
// define liquidation cool off time here. if needed to be defined per asset, populate the liquidationCoolOffTimeOverride mapping
38+
cluster.liquidationCoolOffTime = 1;
39+
40+
// define hook target and hooked ops here. if needed to be defined per asset, populate the hookTargetOverride and hookedOpsOverride mappings
41+
cluster.hookTarget = address(0);
42+
cluster.hookedOps = 0;
43+
44+
// define config flags here. if needed to be defined per asset, populate the configFlagsOverride mapping
45+
cluster.configFlags = 0;
46+
47+
// define oracle providers here.
48+
// adapter names can be found in the relevant adapter contract (as returned by the `name` function).
49+
// for cross adapters, use the following format: "CrossAdapter=<adapterName1>+<adapterName2>".
50+
// although Redstone Classic oracles reuse the ChainlinkOracle contract and returns "ChainlinkOracle" name,
51+
// they should be referred to as "RedstoneClassicOracle".
52+
// in case the asset is an ERC4626 vault itself (i.e. sUSDS) and is recognized as a valid external vault as per
53+
// External Vaults Registry, the string should be preceeded by "ExternalVault|" prefix. this is in order to resolve
54+
// the asset (vault) in the oracle router.
55+
// in case the adapter is not present in the Adapter Registry, the adapter address can be passed instead in form of a string.
56+
cluster.oracleProviders[PT_syrupUSDT_29JAN2026] = "0x546983A4536F204A5b420F5CFa32a671dec6aCaD";
57+
cluster.oracleProviders[USDT0] = "0xE8947CFd3f04E686741F7Dd9023ec0C78588fd33";
58+
59+
// define supply caps here. 0 means no supply can occur, type(uint256).max means no cap defined hence max amount
60+
cluster.supplyCaps[PT_syrupUSDT_29JAN2026] = type(uint256).max;
61+
cluster.supplyCaps[USDe] = type(uint256).max;
62+
cluster.supplyCaps[USDT0] = type(uint256).max;
63+
64+
// define borrow caps here. 0 means no borrow can occur, type(uint256).max means no cap defined hence max amount
65+
cluster.borrowCaps[PT_syrupUSDT_29JAN2026] = type(uint256).max;
66+
cluster.borrowCaps[USDe] = type(uint256).max;
67+
cluster.borrowCaps[USDT0] = type(uint256).max;
68+
69+
// define IRM classes here and assign them to the assets
70+
cluster.irms[USDT0] = IRM_ADAPTIVE_USD;
71+
72+
// define the ramp duration to be used, in case the liquidation LTVs have to be ramped down
73+
cluster.rampDuration = 1 days;
74+
75+
// define the spread between borrow and liquidation ltv
76+
cluster.spreadLTV = 0.02e4;
77+
78+
// define ltv values here. columns are liability vaults, rows are collateral vaults
79+
cluster.ltvs = [
80+
// 0 1
81+
// PT-syrup USDT0
82+
/* 0 PT-syrup*/ [LTV_ZERO, LTV__LOW],
83+
/* 1 USDT0 */ [LTV_ZERO, LTV_ZERO]
84+
];
85+
86+
// define external ltvs here. columns are liability vaults, rows are collateral vaults.
87+
// double check the order of collaterals against the order of externalVaults in the addresses file
88+
}
89+
90+
function postOperations() internal view override {
91+
for (uint256 i = 0; i < cluster.vaults.length; ++i) {
92+
OracleVerifier.verifyOracleConfig(lensAddresses.oracleLens, cluster.vaults[i], false);
93+
}
94+
}
95+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"externalVaults": [],
3+
"irms": [
4+
"0x0000000000000000000000000000000000000000",
5+
"0xf41D1f354f04A2887682ba3585Bf6cCca0a24551",
6+
"0xf41D1f354f04A2887682ba3585Bf6cCca0a24551"
7+
],
8+
"oracleRouters": [
9+
"0xAD950C61d3dCDDCb8972C0937c2276E2cdB703b9",
10+
"0xAD950C61d3dCDDCb8972C0937c2276E2cdB703b9",
11+
"0xAD950C61d3dCDDCb8972C0937c2276E2cdB703b9"
12+
],
13+
"stubOracle": "0x0000000000000000000000000000000000000000",
14+
"vaults": [
15+
"0x5DccE5f1eDdf4c1Ada8Bcf2da89d4bc7fB9Dd5d2",
16+
"0x8539f99dBC4F437C1F71de6920369B9cD46193Ff",
17+
"0x98d6863fa1C247d529c94e53f521897ae9A6EBf0"
18+
]
19+
}

0 commit comments

Comments
 (0)