Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(bundler): add blue tests #30

Merged
merged 25 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7f19c6b
test(bulker): add blue tests
Rubilmax Aug 11, 2023
fae7b47
test(bulker): add fork test
Rubilmax Aug 11, 2023
c95cfd8
Merge branch 'test/bulker' of github.com:morpho-labs/morpho-blue-peri…
Rubilmax Aug 11, 2023
6c20545
Merge branch 'main' of github.com:morpho-labs/morpho-blue-periphery i…
MerlinEgalite Aug 18, 2023
df5c288
Merge branch 'main' of github.com:morpho-labs/morpho-blue-periphery i…
Rubilmax Aug 21, 2023
8336a19
refactor(test): add markets config
Rubilmax Aug 22, 2023
8afdde5
Merge branches 'test/bulker-2' and 'main' of github.com:morpho-labs/m…
Rubilmax Aug 22, 2023
35104fb
refactor(config): complete config markets
Rubilmax Aug 22, 2023
bcaf97e
refactor(price-scale): use Morpho's fixed price scale
Rubilmax Aug 22, 2023
c940089
Merge branch 'refactor/price-scale' of github.com:morpho-labs/morpho-…
Rubilmax Aug 22, 2023
ffc89f1
refactor(fork-test): create config markets
Rubilmax Aug 22, 2023
830f3c1
Merge branch 'main' of github.com:morpho-labs/morpho-blue-periphery i…
Rubilmax Aug 23, 2023
f3fec1c
test(setUp): refactor inheritance
Rubilmax Aug 23, 2023
f8a1791
test(base): deploy Morpho using nested compilation
Rubilmax Aug 23, 2023
5884743
ci(foundry): compile Morpho
Rubilmax Aug 23, 2023
d987bdb
ci(foundry): add debug arg
Rubilmax Aug 23, 2023
bfaac01
test(invariant): remove invariants
Rubilmax Aug 23, 2023
576c796
ci(forge): add specific test to ci
Rubilmax Aug 23, 2023
e6c67bd
test(ethereum): add permit2 test
Rubilmax Aug 23, 2023
4590313
build(lib): bump morpho-blue
Rubilmax Aug 23, 2023
b410b2c
test(irm): remove constructor arg
Rubilmax Aug 23, 2023
4225d88
build(morpho-blue): bump morpho-blue
Rubilmax Aug 23, 2023
f7a96f4
test(local): label Morpho
Rubilmax Aug 23, 2023
af0bfad
test(mainnet): fix balanceOf
Rubilmax Aug 23, 2023
b77b297
refactor(sig-utils): use constants lib
Rubilmax Aug 23, 2023
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
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
NETWORK=ethereum-mainnet
ALCHEMY_KEY=
90 changes: 82 additions & 8 deletions .github/workflows/foundry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,34 @@ concurrency:
cancel-in-progress: true

jobs:
forge-test:
build-via-ir:
name: Compilation (via IR)
runs-on: ubuntu-latest

steps:
- name: Generate a token
id: generate-token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
Rubilmax marked this conversation as resolved.
Show resolved Hide resolved
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Checkout
uses: actions/checkout@v3
with:
token: ${{ steps.generate-token.outputs.token }}
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Build contracts via IR & check sizes
run: make contracts # don't use compilation cache

test-local:
name: Local tests
runs-on: ubuntu-latest

strategy:
fail-fast: true
matrix:
Expand All @@ -21,15 +48,60 @@ jobs:
- type: "slow"
fuzz-runs: 100000
max-test-rejects: 500000
invariant-runs: 1000
invariant-depth: 100
invariant-runs: 64
invariant-depth: 1024
- type: "fast"
fuzz-runs: 256
max-test-rejects: 65536
invariant-runs: 256
invariant-depth: 15
invariant-runs: 16
invariant-depth: 256

steps:
- name: Generate a token
id: generate-token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Checkout
uses: actions/checkout@v3
with:
token: ${{ steps.generate-token.outputs.token }}
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Run local tests in ${{ matrix.type }} mode
run: make test-local
env:
FOUNDRY_FUZZ_RUNS: ${{ matrix.fuzz-runs }}
FOUNDRY_FUZZ_MAX_TEST_REJECTS: ${{ matrix.max-test-rejects }}
FOUNDRY_INVARIANT_RUNS: ${{ matrix.invariant-runs }}
FOUNDRY_INVARIANT_DEPTH: ${{ matrix.invariant-depth }}
FOUNDRY_FUZZ_SEED: 0x${{ github.event.pull_request.base.sha || github.sha }}

test-mainnet:
name: Ethereum tests
runs-on: ubuntu-latest

strategy:
fail-fast: true
matrix:
type: ["slow", "fast"]
include:
- type: "slow"
fuzz-runs: 1024
max-test-rejects: 65536
invariant-runs: 64
invariant-depth: 1024
- type: "fast"
fuzz-runs: 256
max-test-rejects: 65536
invariant-runs: 16
invariant-depth: 256

steps:
- name: Generate a token
id: generate-token
Expand All @@ -41,16 +113,18 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
with:
token: ${{ steps.generate-token.outputs.token }}
token: ${{ steps.generate-token.outputs.token }}
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Run Forge tests in ${{ matrix.type }} mode
run: forge test -vvv
- name: Run mainnet tests in ${{ matrix.type }} mode
run: make test-mainnet
env:
ALCHEMY_KEY: ${{ secrets.ALCHEMY_KEY }}
FOUNDRY_FUZZ_RUNS: ${{ matrix.fuzz-runs }}
FOUNDRY_FUZZ_MAX_TEST_REJECTS: ${{ matrix.max-test-rejects }}
FOUNDRY_INVARIANT_RUNS: ${{ matrix.invariant-runs }}
FOUNDRY_INVARIANT_DEPTH: ${{ matrix.invariant-depth }}
FOUNDRY_FUZZ_SEED: 0x${{ github.event.pull_request.base.sha || github.sha }}
1 change: 1 addition & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
[submodule "lib/morpho-blue"]
path = lib/morpho-blue
url = https://github.com/morpho-labs/morpho-blue
branch = 0.8.21
Rubilmax marked this conversation as resolved.
Show resolved Hide resolved
[submodule "lib/solmate"]
path = lib/solmate
url = https://github.com/transmissions11/solmate
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,20 @@ install:
foundryup
forge install

blue:
cd lib/morpho-blue/ && FOUNDRY_TEST=/dev/null FOUNDRY_SCRIPT=/dev/null forge build --via-ir

contracts:
FOUNDRY_TEST=/dev/null FOUNDRY_SCRIPT=/dev/null forge build --via-ir --extra-output-files irOptimized --sizes --force


test:
test-mainnet:
@FOUNDRY_MATCH_CONTRACT=EthereumTest make test

test-local:
@FOUNDRY_MATCH_CONTRACT=LocalTest make test

test: blue
forge test -vvv


Expand Down
87 changes: 87 additions & 0 deletions config/ConfigLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.0;

import {stdJson} from "@forge-std/StdJson.sol";

struct Config {
string json;
}

/// @dev Warning: keys must be ordered alphabetically.
struct RawConfigMarket {
string borrowableToken;
address chainlinkFeed;
string collateralToken;
uint256 lltv;
}

struct ConfigMarket {
address collateralToken;
address borrowableToken;
address chainlinkFeed;
uint256 lltv;
}

library ConfigLib {
using stdJson for string;

string internal constant CHAIN_ID_PATH = "$.chainId";
string internal constant RPC_ALIAS_PATH = "$.rpcAlias";
string internal constant FORK_BLOCK_NUMBER_PATH = "$.forkBlockNumber";
string internal constant MARKETS_PATH = "$.markets";
string internal constant WRAPPED_NATIVE_PATH = "$.wrappedNative";
string internal constant LSD_NATIVES_PATH = "$.lsdNatives";

function getAddress(Config storage config, string memory key) internal returns (address) {
return config.json.readAddress(string.concat("$.", key));
}

function getAddressArray(Config storage config, string[] memory keys)
internal
returns (address[] memory addresses)
{
addresses = new address[](keys.length);

for (uint256 i; i < keys.length; ++i) {
addresses[i] = getAddress(config, keys[i]);
}
}

function getChainId(Config storage config) internal returns (uint256) {
return config.json.readUint(CHAIN_ID_PATH);
}

function getRpcAlias(Config storage config) internal returns (string memory) {
return config.json.readString(RPC_ALIAS_PATH);
}

function getForkBlockNumber(Config storage config) internal returns (uint256) {
return config.json.readUint(FORK_BLOCK_NUMBER_PATH);
}

function getWrappedNative(Config storage config) internal returns (address) {
return getAddress(config, config.json.readString(WRAPPED_NATIVE_PATH));
}

function getLsdNatives(Config storage config) internal returns (address[] memory) {
return getAddressArray(config, config.json.readStringArray(LSD_NATIVES_PATH));
}

function getMarkets(Config storage config) internal returns (ConfigMarket[] memory markets) {
bytes memory encodedMarkets = config.json.parseRaw(MARKETS_PATH);
RawConfigMarket[] memory rawMarkets = abi.decode(encodedMarkets, (RawConfigMarket[]));

markets = new ConfigMarket[](rawMarkets.length);

for (uint256 i; i < rawMarkets.length; ++i) {
RawConfigMarket memory rawMarket = rawMarkets[i];

markets[i] = ConfigMarket({
collateralToken: getAddress(config, rawMarket.collateralToken),
borrowableToken: getAddress(config, rawMarket.borrowableToken),
chainlinkFeed: rawMarket.chainlinkFeed,
lltv: rawMarket.lltv
});
}
}
}
62 changes: 62 additions & 0 deletions config/Configured.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.0;

import {Config, ConfigMarket, ConfigLib} from "./ConfigLib.sol";

import {StdChains, VmSafe} from "@forge-std/StdChains.sol";

abstract contract Configured is StdChains {
using ConfigLib for Config;

VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));

Config internal config;

address internal dai;
address internal usdc;
address internal usdt;
address internal link;
address internal wbtc;
address internal weth;
address internal wNative;
address[] internal lsdNatives;
address[] internal allAssets;

ConfigMarket[] internal configMarkets;

function _network() internal view virtual returns (string memory);

function _rpcAlias() internal virtual returns (string memory) {
return config.getRpcAlias();
}

function _initConfig() internal returns (Config storage) {
if (bytes(config.json).length == 0) {
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/config/", _network(), ".json");

config.json = vm.readFile(path);
}

return config;
}

function _loadConfig() internal virtual {
dai = config.getAddress("DAI");
usdc = config.getAddress("USDC");
usdt = config.getAddress("USDT");
link = config.getAddress("LINK");
wbtc = config.getAddress("WBTC");
weth = config.getAddress("WETH");
wNative = config.getWrappedNative();
lsdNatives = config.getLsdNatives();

allAssets = [dai, usdc, usdt, link, wbtc, weth];

configMarkets = config.getMarkets();

for (uint256 i; i < lsdNatives.length; ++i) {
allAssets.push(lsdNatives[i]);
}
}
}
28 changes: 28 additions & 0 deletions config/ethereum-mainnet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"chainId": 1,
"rpcAlias": "mainnet",
"forkBlockNumber": 17891982,
"markets": [
{
"borrowableToken": "WETH",
"collateralToken": "DAI",
"chainlinkFeed": "0x773616E4d11A78F511299002da57A0a94577F1f4",
"lltv": 800000000000000000
}
],
"DAI": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
"USDC": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"USDT": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
"LINK": "0x514910771AF9Ca656af840dff83E8264EcF986CA",
"WBTC": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
"WETH": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"wstETH": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
"cbETH": "0xBe9895146f7AF43049ca1c1AE358B0541Ea49704",
"rETH": "0xae78736Cd615f374D3085123A210448E74Fc6393",
"wrappedNative": "WETH",
"lsdNatives": [
"wstETH",
"cbETH",
"rETH"
]
}
12 changes: 8 additions & 4 deletions contracts/bundlers/MorphoBundler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,16 @@ abstract contract MorphoBundler is BaseBundler, IMorphoBundler {
}

/// @dev Triggers a liquidation on Blue.
function morphoLiquidate(MarketParams calldata marketparams, address borrower, uint256 seized, bytes memory data)
external
{
function morphoLiquidate(
MarketParams calldata marketparams,
address borrower,
uint256 seizedAssets,
uint256 repaidShares,
bytes memory data
) external {
_approveMaxBlue(marketparams.borrowableToken);

MORPHO.liquidate(marketparams, borrower, seized, data);
MORPHO.liquidate(marketparams, borrower, seizedAssets, repaidShares, data);
}

/// @dev Triggers a flash loan on Blue.
Expand Down
8 changes: 4 additions & 4 deletions contracts/meta-morpho/SupplyVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,28 @@ import {MarketAllocation} from "./libraries/Types.sol";
import {IMorpho, MorphoLib} from "@morpho-blue/libraries/periphery/MorphoLib.sol";
import {UnauthorizedMarket, InconsistentAsset, SupplyCapExceeded} from "./libraries/Errors.sol";
import {MarketConfig, MarketConfigData, ConfigSet, ConfigSetLib} from "./libraries/ConfigSetLib.sol";
import {Id, MarketParams, MarketLib} from "@morpho-blue/libraries/MarketLib.sol";
import {Id, MarketParams, MarketParamsLib} from "@morpho-blue/libraries/MarketParamsLib.sol";
import {SharesMathLib} from "@morpho-blue/libraries/SharesMathLib.sol";

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {InternalSupplyRouter, ERC2771Context} from "./InternalSupplyRouter.sol";
import {IERC20, ERC20, ERC4626, Context} from "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol";

contract SupplyVault is ISupplyVault, ERC4626, Ownable, InternalSupplyRouter {
contract SupplyVault is ISupplyVault, InternalSupplyRouter, ERC4626, Ownable {
using MorphoLib for IMorpho;
using SharesMathLib for uint256;
using ConfigSetLib for ConfigSet;
using MarketLib for MarketParams;
using MarketParamsLib for MarketParams;

address private _riskManager;
address private _allocationManager;

ConfigSet private _config;

constructor(address morpho, address forwarder, string memory name_, string memory symbol_, IERC20 asset_)
InternalSupplyRouter(morpho, forwarder)
ERC20(name_, symbol_)
ERC4626(asset_)
InternalSupplyRouter(morpho, forwarder)
{}

modifier onlyRiskManager() {
Expand Down
Loading