Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7ba14e9
Add OEV fix to ChainlinkOracleProxy
anajuliabit Oct 15, 2025
aa45895
add natspec comments
anajuliabit Oct 16, 2025
1fc5908
approve first
anajuliabit Oct 16, 2025
c1fad88
add todo
anajuliabit Oct 16, 2025
0a29669
fix compile issues
imthatcarlos Oct 16, 2025
f84fc01
rewrite latestRoundData logic for clarity
anajuliabit Oct 16, 2025
51ef38d
update errors description
anajuliabit Oct 16, 2025
35074fb
fix imports
imthatcarlos Oct 16, 2025
0047b33
Merge branch 'fix/oev-wrapper' of github.com:moonwell-fi/moonwell-con…
imthatcarlos Oct 16, 2025
7ee5443
conf
imthatcarlos Oct 16, 2025
2fb0162
add ChaininkOEVMorphoWrapper
anajuliabit Oct 16, 2025
ca199b0
add excess funds logic
anajuliabit Oct 16, 2025
e98a412
compile
anajuliabit Oct 17, 2025
8669756
Merge branch 'main' into fix/oev-wrapper
anajuliabit Oct 30, 2025
f6bcd7e
Merge branch 'main' into fix/oev-wrapper
anajuliabit Nov 3, 2025
ef8f9fe
Merge branch 'main' into fix/oev-wrapper
anajuliabit Nov 7, 2025
37ec3f7
wip - updating test but failing due to mip x36
imthatcarlos Nov 11, 2025
ace94e8
Merge branch 'fix/oev-wrapper' into fix/oev-wrapper-tests
imthatcarlos Nov 11, 2025
1a514d2
deprecated oracle proxy stuff
imthatcarlos Nov 11, 2025
a31d959
more formatting?
imthatcarlos Nov 11, 2025
76e41ab
rename => mip-x37.sol; core wrapper integration tests passing
imthatcarlos Nov 11, 2025
bfb338d
fix morpho tests
imthatcarlos Nov 11, 2025
8e7eda1
update ci
imthatcarlos Nov 12, 2025
c349f5d
more validations for constructor
imthatcarlos Nov 12, 2025
f3655e9
add: real liquidation scenario; fix usd collateral fee split; liquida…
imthatcarlos Nov 14, 2025
d1c673e
skip cbETH for now
imthatcarlos Nov 17, 2025
5956bb2
fix test by mocking eth price
imthatcarlos Nov 17, 2025
413e63c
fix test for real liquidations per chain
imthatcarlos Nov 17, 2025
a32c53a
Merge branch 'main' into fix/oev-wrapper-tests
imthatcarlos Nov 18, 2025
8a46b78
new contract OEVProtocolFeeRedeemer to receive all oev fees (mtoken o…
imthatcarlos Nov 19, 2025
3af3058
lint
imthatcarlos Nov 19, 2025
d9cfb5c
tests: remove note on stkwell, require borrow
imthatcarlos Nov 19, 2025
3a926d5
fix: CHAINLINK_ORACLE_PROXY_ADMIN
imthatcarlos Nov 19, 2025
73d1eec
fix cbETH test case
imthatcarlos Nov 19, 2025
e688eb3
fix: mtokens must be whitelisted on redeemer contract
imthatcarlos Nov 19, 2025
f1fd618
tests: update logs to reflect mtokens + redemptions; add more real li…
imthatcarlos Nov 20, 2025
2e3b3a0
add all markets; update tests; remove logs from mip
imthatcarlos Nov 21, 2025
427b234
Merge branch 'main' into fix/oev-wrapper-tests
imthatcarlos Nov 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions .github/workflows/base-integration.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Base
name: Base

on: [pull_request]

Expand Down Expand Up @@ -121,7 +121,7 @@ jobs:
retry_wait_seconds: 60
timeout_minutes: 20
max_attempts: 3
command: time forge test --match-contract CypherIntegrationTest --fork-url base -vvv
command: time forge test --match-contract CypherIntegrationTest --fork-url base -vvv

bounded-chainlink-composite-oracle:
name: Bounded Chainlink Composite Oracle Test
Expand All @@ -147,8 +147,8 @@ jobs:
max_attempts: 3
command: time forge test --mc "ChainlinkBoundedCompositeOracleIntegrationTest" -vvv --ffi

chainlink-oracle-proxy:
name: Chainlink Oracle Proxy Test
chainlink-oev-wrapper:
name: Chainlink OEV Wrapper Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
Expand All @@ -169,5 +169,28 @@ jobs:
retry_wait_seconds: 60
timeout_minutes: 20
max_attempts: 3
command: time forge test --mc "ChainlinkOracleProxyIntegrationTest" -vvv --ffi
command: time forge test --mc "ChainlinkOEVWrapperIntegration" -vvv --ffi

chainlink-oev-morpho-wrapper:
name: Chainlink OEV Morpho Wrapper Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
with:
submodules: recursive

- name: Setup Environment
uses: ./.github/actions

- name: Setup MIPs Permissions
uses: ./.github/actions/setup-mips-permissions

- name: Run Integration Tests
uses: nick-fields/retry@v3
with:
polling_interval_seconds: 30
retry_wait_seconds: 60
timeout_minutes: 20
max_attempts: 3
command: time forge test --mc "ChainlinkOEVMorphoWrapperIntegration" -vvv --ffi
185 changes: 185 additions & 0 deletions proposals/ChainlinkOracleConfigs.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
pragma solidity 0.8.19;

import "@forge-std/Test.sol";
import "@utils/ChainIds.sol";

abstract contract ChainlinkOracleConfigs is Test {
struct OracleConfig {
string oracleName; /// e.g., CHAINLINK_ETH_USD
string symbol; /// e.g., as found in addresses
string mTokenKey; /// e.g., MOONWELL_WETH (defaults to MOONWELL_[symbol] if not specified)
}

struct MorphoOracleConfig {
string proxyName; /// e.g., CHAINLINK_stkWELL_USD (used for proxy identifier)
string priceFeedName; /// e.g., CHAINLINK_WELL_USD (the actual price feed oracle)
}

/// oracle configurations per chain id
mapping(uint256 => OracleConfig[]) internal _oracleConfigs;

/// morpho market configurations per chain id
mapping(uint256 => MorphoOracleConfig[]) internal _MorphoOracleConfigs;

/// @dev oracles are listed in the order they are in the docs
/// https://docs.moonwell.fi/moonwell/protocol-information/contracts#base-contract-addresses
/// NOTE: some oracles are commented out as they have composite oracles, or won't be part of the mip to have oev wrapper
constructor() {
/// Initialize oracle configurations for Base
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("DAI_ORACLE", "DAI", "MOONWELL_DAI")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_USDC_USD", "USDC", "MOONWELL_USDC")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_USDC_USD", "USDBC", "MOONWELL_USDBC")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_ETH_USD", "WETH", "MOONWELL_WETH")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("cbETHETH_ORACLE", "cbETH", "MOONWELL_cbETH")
);
// _oracleConfigs[BASE_CHAIN_ID].push(
// OracleConfig("CHAINLINK_WSTETH_STETH_COMPOSITE_ORACLE", "wstETH", "MOONWELL_wstETH")
// );
// _oracleConfigs[BASE_CHAIN_ID].push(
// OracleConfig("CHAINLINK_RETH_ETH_COMPOSITE_ORACLE", "rETH", "MOONWELL_rETH")
// );
// _oracleConfigs[BASE_CHAIN_ID].push(
// OracleConfig("CHAINLINK_WEETH_USD_COMPOSITE_ORACLE", "weETH", "MOONWELL_weETH")
// );
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_AERO_ORACLE", "AERO", "MOONWELL_AERO")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_BTC_USD", "cbBTC", "MOONWELL_cbBTC")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_EURC_USD", "EURC", "MOONWELL_EURC")
);
// _oracleConfigs[BASE_CHAIN_ID].push(
// OracleConfig("CHAINLINK_wrsETH_COMPOSITE_ORACLE", "wrsETH", "MOONWELL_wrsETH")
// );
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_WELL_USD", "xWELL_PROXY", "MOONWELL_WELL")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_USDS_USD", "USDS", "MOONWELL_USDS")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_TBTC_USD", "TBTC", "MOONWELL_TBTC")
);
// _oracleConfigs[BASE_CHAIN_ID].push(
// OracleConfig("CHAINLINK_LBTC_BTC_COMPOSITE_ORACLE", "LBTC", "MOONWELL_LBTC")
// );
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_VIRTUAL_USD", "VIRTUAL", "MOONWELL_VIRTUAL")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_MORPHO_USD", "MORPHO", "MOONWELL_MORPHO")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_cbXRP_USD", "cbXRP", "MOONWELL_cbXRP")
);
_oracleConfigs[BASE_CHAIN_ID].push(
OracleConfig("CHAINLINK_MAMO_USD", "MAMO", "MOONWELL_MAMO")
);

/// Initialize oracle configurations for Optimism
_oracleConfigs[OPTIMISM_CHAIN_ID].push(
OracleConfig("CHAINLINK_USDC_USD", "USDC", "MOONWELL_USDC")
);
_oracleConfigs[OPTIMISM_CHAIN_ID].push(
OracleConfig("CHAINLINK_USDT_USD", "USDT", "MOONWELL_USDT")
);
_oracleConfigs[OPTIMISM_CHAIN_ID].push(
OracleConfig("CHAINLINK_DAI_USD", "DAI", "MOONWELL_DAI")
);
_oracleConfigs[OPTIMISM_CHAIN_ID].push(
OracleConfig("CHAINLINK_ETH_USD", "WETH", "MOONWELL_WETH")
);
_oracleConfigs[OPTIMISM_CHAIN_ID].push(
OracleConfig("CHAINLINK_WBTC_USD", "WBTC", "MOONWELL_WBTC")
);
// _oracleConfigs[OPTIMISM_CHAIN_ID].push(
// OracleConfig("CHAINLINK_WSTETH_USD_COMPOSITE_ORACLE", "wstETH", "MOONWELL_wstETH")
// );
// _oracleConfigs[OPTIMISM_CHAIN_ID].push(
// OracleConfig("CHAINLINK_cbETH_USD_COMPOSITE_ORACLE", "cbETH", "MOONWELL_cbETH")
// );
// _oracleConfigs[OPTIMISM_CHAIN_ID].push(
// OracleConfig("CHAINLINK_RETH_USD_COMPOSITE_ORACLE", "rETH", "MOONWELL_rETH")
// );
// _oracleConfigs[OPTIMISM_CHAIN_ID].push(
// OracleConfig("CHAINLINK_WEETH_USD_COMPOSITE_ORACLE", "weETH", "MOONWELL_weETH")
// );
_oracleConfigs[OPTIMISM_CHAIN_ID].push(
OracleConfig("CHAINLINK_OP_USD", "OP", "MOONWELL_OP")
);
_oracleConfigs[OPTIMISM_CHAIN_ID].push(
OracleConfig("CHAINLINK_VELO_USD", "VELO", "MOONWELL_VELO")
);
// _oracleConfigs[OPTIMISM_CHAIN_ID].push(
// OracleConfig("CHAINLINK_wrsETH_COMPOSITE_ORACLE", "wrsETH", "MOONWELL_wrsETH")
// );
_oracleConfigs[OPTIMISM_CHAIN_ID].push(
OracleConfig("CHAINLINK_USDT_USD", "USDT0", "MOONWELL_USDT0")
);

/// Initialize Morpho market configurations for Base
_MorphoOracleConfigs[BASE_CHAIN_ID].push(
MorphoOracleConfig("CHAINLINK_WELL_USD", "CHAINLINK_WELL_USD")
);
_MorphoOracleConfigs[BASE_CHAIN_ID].push(
MorphoOracleConfig("CHAINLINK_MAMO_USD", "CHAINLINK_MAMO_USD")
);

_MorphoOracleConfigs[BASE_CHAIN_ID].push(
MorphoOracleConfig("CHAINLINK_stkWELL_USD", "CHAINLINK_WELL_USD")
);
}

function getOracleConfigurations(
uint256 chainId
) public view returns (OracleConfig[] memory) {
OracleConfig[] memory configs = new OracleConfig[](
_oracleConfigs[chainId].length
);

unchecked {
uint256 configLength = configs.length;
for (uint256 i = 0; i < configLength; i++) {
configs[i] = OracleConfig({
oracleName: _oracleConfigs[chainId][i].oracleName,
symbol: _oracleConfigs[chainId][i].symbol,
mTokenKey: _oracleConfigs[chainId][i].mTokenKey
});
}
}

return configs;
}

function getMorphoOracleConfigurations(
uint256 chainId
) public view returns (MorphoOracleConfig[] memory) {
MorphoOracleConfig[] memory configs = new MorphoOracleConfig[](
_MorphoOracleConfigs[chainId].length
);

unchecked {
uint256 configLength = configs.length;
for (uint256 i = 0; i < configLength; i++) {
configs[i] = MorphoOracleConfig({
proxyName: _MorphoOracleConfigs[chainId][i].proxyName,
priceFeedName: _MorphoOracleConfigs[chainId][i]
.priceFeedName
});
}
}

return configs;
}
}
6 changes: 3 additions & 3 deletions proposals/mips/mip-o12/mip-o12.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import {ERC20} from "@openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
import {ProposalActions} from "@proposals/utils/ProposalActions.sol";
import {OPTIMISM_FORK_ID} from "@utils/ChainIds.sol";
import {ChainlinkFeedOEVWrapper} from "@protocol/oracles/ChainlinkFeedOEVWrapper.sol";
import {DeployChainlinkOEVWrapper} from "@script/DeployChainlinkOEVWrapper.sol";
import {HybridProposal, ActionType} from "@proposals/proposalTypes/HybridProposal.sol";
import {AllChainAddresses as Addresses} from "@proposals/Addresses.sol";

contract mipo12 is HybridProposal, DeployChainlinkOEVWrapper {
contract mipo12 is HybridProposal {
using ProposalActions for *;

string public constant override name = "MIP-O12";
Expand All @@ -31,7 +30,8 @@ contract mipo12 is HybridProposal, DeployChainlinkOEVWrapper {

function deploy(Addresses addresses, address) public override {
if (!addresses.isAddressSet("CHAINLINK_ETH_USD_OEV_WRAPPER")) {
deployChainlinkOEVWrapper(addresses, "CHAINLINK_ETH_USD");
// new version of deploy script not compatiblw with old wrapper
//deployChainlinkOEVWrapper(addresses, "CHAINLINK_ETH_USD");
}
}

Expand Down
21 changes: 11 additions & 10 deletions proposals/mips/mip-x14/mip-x14.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ import {ERC20} from "@openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
import {ProposalActions} from "@proposals/utils/ProposalActions.sol";
import {ChainlinkFeedOEVWrapper} from "@protocol/oracles/ChainlinkFeedOEVWrapper.sol";
import {ChainlinkCompositeOracle} from "@protocol/oracles/ChainlinkCompositeOracle.sol";
import {DeployChainlinkOEVWrapper} from "@script/DeployChainlinkOEVWrapper.sol";
import {HybridProposal, ActionType} from "@proposals/proposalTypes/HybridProposal.sol";
import {AllChainAddresses as Addresses} from "@proposals/Addresses.sol";
import {OPTIMISM_FORK_ID, BASE_FORK_ID, OPTIMISM_CHAIN_ID, BASE_CHAIN_ID} from "@utils/ChainIds.sol";

contract mipx14 is HybridProposal, DeployChainlinkOEVWrapper {
contract mipx14 is HybridProposal {
using ProposalActions for *;
using ChainIds for uint256;

Expand Down Expand Up @@ -151,10 +150,11 @@ contract mipx14 is HybridProposal, DeployChainlinkOEVWrapper {
)
);
if (!addresses.isAddressSet(wrapperName)) {
deployChainlinkOEVWrapper(
addresses,
_oracleConfigs[OPTIMISM_CHAIN_ID][i].oracleName
);
// new version of deploy script not compatiblw with old wrapper
//deployChainlinkOEVWrapper(
// addresses,
// _oracleConfigs[OPTIMISM_CHAIN_ID][i].oracleName
//);
}
}
vm.stopBroadcast();
Expand All @@ -170,10 +170,11 @@ contract mipx14 is HybridProposal, DeployChainlinkOEVWrapper {
)
);
if (!addresses.isAddressSet(wrapperName)) {
deployChainlinkOEVWrapper(
addresses,
_oracleConfigs[BASE_CHAIN_ID][i].oracleName
);
// new version of deploy script not compatiblw with old wrapper
//deployChainlinkOEVWrapper(
// addresses,
// _oracleConfigs[BASE_CHAIN_ID][i].oracleName
//);
}
}

Expand Down
Loading
Loading