// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Script, console} from "forge-std/Script.sol"; import {Aggregator} from "../../contracts/oracle/Aggregator.sol"; interface IOraclePriceFeedWire { function aggregators(address asset) external view returns (address); function setAggregator(address asset, address aggregator, uint256 multiplier) external; function updatePriceFeed(address asset) external; function setUpdateInterval(uint256 interval) external; function updateInterval() external view returns (uint256); } interface IPriceFeedKeeperWire { function isTracked(address asset) external view returns (bool); function trackAsset(address asset) external; function maxUpdatesPerCall() external view returns (uint256); function setMaxUpdatesPerCall(uint256 max) external; } interface IDODOPMMIntegrationWire { function setReserveSystem(address reserveSystem_) external; function reserveSystem() external view returns (address); } interface IReserveSystemWire { function updatePriceFeed(address asset, uint256 price, uint256 timestamp) external; } interface IAggregatorWire { function addTransmitter(address transmitter) external; function updateAnswer(uint256 answer) external; function isTransmitter(address transmitter) external view returns (bool); function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); } /// @notice Wire canonical Chain 138 assets to Chainlink-mirrored repo aggregators + keeper + reserve. contract WireChain138OraclePegs138 is Script { uint256 internal constant MULT = 1e10; address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address internal constant WETH10 = 0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F; address internal constant LINK = 0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03; address internal constant CUSDT = 0x93E66202A11B1772E55407B32B44e5Cd8eda7f22; address internal constant CUSDC = 0xf22258f57794CC8E06237084b353Ab30fFfa640b; address internal constant CEURC = 0x8085961F9cF02b4d800A3c6d386D31da4B34266a; address internal constant CEURT = 0xdf4b71c61E5912712C1Bdd451416B9aC26949d72; address internal constant CGBPC = 0x003960f16D9d34F2e98d62723B6721Fb92074aD2; address internal constant CGBPT = 0x350f54e4D23795f86A9c03988c7135357CCaD97c; address internal constant CAUDC = 0xD51482e567c03899eecE3CAe8a058161FD56069D; address internal constant CJPYC = 0xEe269e1226a334182aace90056EE4ee5Cc8A6770; address internal constant CCHFC = 0x873990849DDa5117d7C644f0aF24370797C03885; address internal constant CCADC = 0x54dBd40cF05e15906A2C21f600937e96787f5679; address internal constant CXAUC = 0x290E52a8819A4fbD0714E517225429aA2B70EC6b; address internal constant CXAUT = 0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E; address internal constant CBTC = 0xe94260c555aC1d9D3CC9E1632883452ebDf0082E; function run() external { require(block.chainid == 138, "ChainID 138 only"); uint256 pk = vm.envUint("PRIVATE_KEY"); address deployer = vm.addr(pk); address opf = vm.envAddress("ORACLE_PRICE_FEED"); address keeperAddr = vm.envAddress("PRICE_FEED_KEEPER_ADDRESS"); address rs = vm.envAddress("RESERVE_SYSTEM"); address ethAgg = vm.envAddress("AGGREGATOR_ADDRESS"); address dodo = vm.envAddress("CHAIN_138_DODO_PMM_INTEGRATION"); uint256 ethSeed8 = vm.envOr("FEED_ETH_USD_8", uint256(0)); IOraclePriceFeedWire op = IOraclePriceFeedWire(opf); IPriceFeedKeeperWire keeper = IPriceFeedKeeperWire(keeperAddr); console.log("=== Wire Chain 138 oracle pegs ==="); console.log("Deployer:", deployer); vm.startBroadcast(pk); if (op.updateInterval() != 86400) { try op.setUpdateInterval(86400) {} catch {} } if (ethSeed8 > 0) { IAggregatorWire eth = IAggregatorWire(ethAgg); if (!eth.isTransmitter(deployer)) { try eth.addTransmitter(deployer) {} catch {} } try eth.updateAnswer(ethSeed8) {} catch {} } if (keeper.maxUpdatesPerCall() < 20) { keeper.setMaxUpdatesPerCall(20); } address usdAgg = _deployMirror("USD/USD Chainlink mirror", vm.envUint("FEED_USD_USD_8")); address linkAgg = _deployMirror("LINK/USD Chainlink mirror", vm.envUint("FEED_LINK_USD_8")); address btcAgg = _deployMirror("BTC/USD Chainlink mirror", vm.envUint("FEED_BTC_USD_8")); address xauAgg = _deployMirror("XAU/USD Chainlink mirror", vm.envUint("FEED_XAU_USD_8")); address eurAgg = _deployMirror("EUR/USD Chainlink mirror", vm.envUint("FEED_EUR_USD_8")); address gbpAgg = _deployMirror("GBP/USD Chainlink mirror", vm.envUint("FEED_GBP_USD_8")); address audAgg = _deployMirror("AUD/USD Chainlink mirror", vm.envUint("FEED_AUD_USD_8")); address jpyAgg = _deployMirror("JPY/USD Chainlink mirror", vm.envUint("FEED_JPY_USD_8")); address chfAgg = _deployMirror("CHF/USD Chainlink mirror", vm.envUint("FEED_CHF_USD_8")); address cadAgg = _deployMirror("CAD/USD Chainlink mirror", vm.envUint("FEED_CAD_USD_8")); _wire(op, keeper, rs, WETH9, ethAgg); _wire(op, keeper, rs, WETH10, ethAgg); _wire(op, keeper, rs, LINK, linkAgg); _wire(op, keeper, rs, CUSDT, usdAgg); _wire(op, keeper, rs, CUSDC, usdAgg); _wire(op, keeper, rs, CEURC, eurAgg); _wire(op, keeper, rs, CEURT, eurAgg); _wire(op, keeper, rs, CGBPC, gbpAgg); _wire(op, keeper, rs, CGBPT, gbpAgg); _wire(op, keeper, rs, CAUDC, audAgg); _wire(op, keeper, rs, CJPYC, jpyAgg); _wire(op, keeper, rs, CCHFC, chfAgg); _wire(op, keeper, rs, CCADC, cadAgg); _wire(op, keeper, rs, CXAUC, xauAgg); _wire(op, keeper, rs, CXAUT, xauAgg); _wire(op, keeper, rs, CBTC, btcAgg); IDODOPMMIntegrationWire dodoInt = IDODOPMMIntegrationWire(dodo); if (dodoInt.reserveSystem() != rs) { dodoInt.setReserveSystem(rs); console.log("DODO reserveSystem wired:", rs); } vm.stopBroadcast(); console.log("=== Done ==="); } function _deployMirror(string memory description, uint256 price8) internal returns (address) { require(price8 > 0, "missing seed price"); Aggregator agg = new Aggregator(description, msg.sender, 3600, 50); agg.addTransmitter(msg.sender); agg.updateAnswer(price8); console.log("Deployed feed:", description); console.log(" aggregator:", address(agg)); return address(agg); } function _wire( IOraclePriceFeedWire op, IPriceFeedKeeperWire keeper, address rs, address token, address agg ) internal { require(agg != address(0), "zero aggregator"); if (op.aggregators(token) == address(0)) { op.setAggregator(token, agg, MULT); } if (!keeper.isTracked(token)) { keeper.trackAsset(token); } try op.updatePriceFeed(token) {} catch { (, int256 ans,, uint256 updatedAt,) = IAggregatorWire(agg).latestRoundData(); require(ans > 0, "bad agg price"); IReserveSystemWire(rs).updatePriceFeed(token, uint256(ans) * MULT, updatedAt); } } }