Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 1 deletion solidity/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fs_permissions = [{ access = "read", path = "./deployments" }]
flow_mainnet = "https://mainnet.evm.nodes.onflow.org"

[fmt]
line_length = 100
line_length = 120
tab_width = 4

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
12 changes: 4 additions & 8 deletions solidity/script/ConfiguredScript.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ abstract contract ConfiguredScript is Script {

c.chainId = vm.parseTomlUint(toml, ".chainId");
require(
c.chainId == block.chainid,
string.concat("config chainId does not match RPC chain (network=", network, ")")
c.chainId == block.chainid, string.concat("config chainId does not match RPC chain (network=", network, ")")
);

c.collateral = vm.parseTomlAddress(toml, ".collateral");
Expand Down Expand Up @@ -94,20 +93,17 @@ abstract contract ConfiguredScript is Script {
function _requireMarketExists(Config memory c) internal view returns (Market memory m) {
m = MORPHO.market(_marketId(c));
require(
m.lastUpdate != 0,
"Morpho market for config params does not exist; check marketOracle/marketIrm/marketLltv"
m.lastUpdate != 0, "Morpho market for config params does not exist; check marketOracle/marketIrm/marketLltv"
);
}

/// @dev Both FlowSwap pools the vault trades on must exist.
function _requirePoolsExist(Config memory c) internal view {
address yieldPool =
IUniswapV3Factory(c.swapFactory).getPool(c.yieldToken, c.loanToken, c.feeYieldDebt);
address yieldPool = IUniswapV3Factory(c.swapFactory).getPool(c.yieldToken, c.loanToken, c.feeYieldDebt);
require(yieldPool != address(0), "yield/debt pool missing");
require(yieldPool == c.yieldDebtPool, "config yieldDebtPool does not match factory");
require(
IUniswapV3Factory(c.swapFactory).getPool(c.collateral, c.loanToken, c.feeAssetDebt)
!= address(0),
IUniswapV3Factory(c.swapFactory).getPool(c.collateral, c.loanToken, c.feeAssetDebt) != address(0),
"asset/debt pool missing"
);
}
Expand Down
26 changes: 6 additions & 20 deletions solidity/script/LiveCheck.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,9 @@ contract LiveCheck is Script {
(, address caller,) = vm.readCallers();

// Pre-flight: fail with a clear reason before any value moves.
require(
vault.hasRole(vault.EARLY_ACCESS_ROLE(), caller),
"caller lacks EARLY_ACCESS_ROLE on the vault"
);
require(
assetToken.balanceOf(caller) >= amount,
"caller does not hold CHECK_AMOUNT of the vault asset"
);
require(
vault.maxDeposit(caller) >= amount, "TVL headroom below CHECK_AMOUNT (is maxTvl set?)"
);
require(vault.hasRole(vault.EARLY_ACCESS_ROLE(), caller), "caller lacks EARLY_ACCESS_ROLE on the vault");
require(assetToken.balanceOf(caller) >= amount, "caller does not hold CHECK_AMOUNT of the vault asset");
require(vault.maxDeposit(caller) >= amount, "TVL headroom below CHECK_AMOUNT (is maxTvl set?)");

uint256 assetBefore = assetToken.balanceOf(caller);
uint256 sharesBefore = vault.balanceOf(caller);
Expand All @@ -70,10 +62,7 @@ contract LiveCheck is Script {
assetToken.approve(address(vault), amount);
uint256 shares = vault.deposit(amount, caller);
require(shares > 0, "deposit minted zero shares");
require(
vault.balanceOf(caller) == sharesBefore + shares,
"share balance does not reflect minted shares"
);
require(vault.balanceOf(caller) == sharesBefore + shares, "share balance does not reflect minted shares");
require(vault.totalAssets() > navBefore, "vault NAV did not grow on deposit");

// Rebalance the position. Acts only when HF is outside the [min, max]
Expand All @@ -93,9 +82,7 @@ contract LiveCheck is Script {
"asset balance delta does not match redeem output"
);
uint256 roundtripBps = redeemed * 10_000 / amount;
require(
roundtripBps >= minRoundtripBps, "round-trip value below MIN_ROUNDTRIP_BPS tolerance"
);
require(roundtripBps >= minRoundtripBps, "round-trip value below MIN_ROUNDTRIP_BPS tolerance");

console.log("=== live check passed ===");
console.log("deposited: %s", amount);
Expand All @@ -122,7 +109,6 @@ contract LiveCheck is Script {
Position memory pos = MORPHO.position(mp.id(), address(vault));
if (pos.borrowShares == 0) return 0;
Market memory mkt = MORPHO.market(mp.id());
return uint256(pos.borrowShares)
.toAssetsUp(uint256(mkt.totalBorrowAssets), uint256(mkt.totalBorrowShares));
return uint256(pos.borrowShares).toAssetsUp(uint256(mkt.totalBorrowAssets), uint256(mkt.totalBorrowShares));
}
}
12 changes: 3 additions & 9 deletions solidity/script/Rebalance.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ contract Rebalance is Script {
Position memory pos = MORPHO.position(mp.id(), address(vault));
if (pos.borrowShares == 0) return type(uint256).max;
uint256 debt = _debtFromPosition(mp, pos);
uint256 maxBorrow =
(uint256(pos.collateral) * ((IOracle(mp.oracle).price() * mp.lltv) / 1e36)) / 1e18;
uint256 maxBorrow = (uint256(pos.collateral) * ((IOracle(mp.oracle).price() * mp.lltv) / 1e36)) / 1e18;
return (maxBorrow * 1e18) / debt;
}

Expand All @@ -86,14 +85,9 @@ contract Rebalance is Script {
/// @dev Converts borrow shares to loan-token debt with Morpho's own
/// `SharesMathLib.toAssetsUp`, matching how Morpho charges debt (and
/// the contract's `MarketLib.debt`).
function _debtFromPosition(MarketParams memory mp, Position memory pos)
internal
view
returns (uint256)
{
function _debtFromPosition(MarketParams memory mp, Position memory pos) internal view returns (uint256) {
Market memory mkt = MORPHO.market(mp.id());
return uint256(pos.borrowShares)
.toAssetsUp(uint256(mkt.totalBorrowAssets), uint256(mkt.totalBorrowShares));
return uint256(pos.borrowShares).toAssetsUp(uint256(mkt.totalBorrowAssets), uint256(mkt.totalBorrowShares));
}

function _market(FCMVault vault) internal view returns (MarketParams memory) {
Expand Down
5 changes: 1 addition & 4 deletions solidity/script/SeedMarket.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,7 @@ contract SeedMarket is ConfiguredScript {

vm.startBroadcast();
address supplier = _broadcaster();
require(
IERC20(c.loanToken).balanceOf(supplier) >= amount,
"broadcaster holds less loan token than SEED_AMOUNT"
);
require(IERC20(c.loanToken).balanceOf(supplier) >= amount, "broadcaster holds less loan token than SEED_AMOUNT");

IERC20(c.loanToken).approve(address(MORPHO), amount);
(uint256 supplied,) = MORPHO.supply(_marketParams(c), amount, 0, supplier, "");
Expand Down
10 changes: 3 additions & 7 deletions solidity/script/Status.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ contract Status is ConfiguredScript {

function _reportPools(Config memory c) internal view {
console.log("--- FlowSwap pools");
address yieldPool =
IUniswapV3Factory(c.swapFactory).getPool(c.yieldToken, c.loanToken, c.feeYieldDebt);
address assetPool =
IUniswapV3Factory(c.swapFactory).getPool(c.collateral, c.loanToken, c.feeAssetDebt);
address yieldPool = IUniswapV3Factory(c.swapFactory).getPool(c.yieldToken, c.loanToken, c.feeYieldDebt);
address assetPool = IUniswapV3Factory(c.swapFactory).getPool(c.collateral, c.loanToken, c.feeAssetDebt);
console.log("yield/debt pool (fee %s): %s", c.feeYieldDebt, yieldPool);
console.log("asset/debt pool (fee %s): %s", c.feeAssetDebt, assetPool);
if (yieldPool != c.yieldDebtPool) {
Expand All @@ -71,9 +69,7 @@ contract Status is ConfiguredScript {
try IOracle(c.marketOracle).price() returns (uint256 marketPrice) {
console.log("market oracle price (1e36-scaled): %s", marketPrice);
} catch {
console.log(
"MARKET ORACLE REVERTING (stale Pyth feed?) -- vault operations will fail until it updates"
);
console.log("MARKET ORACLE REVERTING (stale Pyth feed?) -- vault operations will fail until it updates");
}
if (c.yieldOracle != address(0)) {
console.log("yield oracle (configured): %s", c.yieldOracle);
Expand Down
9 changes: 2 additions & 7 deletions solidity/script/SwapForWeth.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ contract SwapForWeth is ConfiguredScript {
uint256 slippageBps = vm.envOr("SLIPPAGE_BPS", uint256(300));
require(slippageBps < BPS, "SLIPPAGE_BPS must be < 10000");

address pool =
IUniswapV3Factory(c.swapFactory).getPool(address(WFLOW), weth, WFLOW_WETH_FEE);
address pool = IUniswapV3Factory(c.swapFactory).getPool(address(WFLOW), weth, WFLOW_WETH_FEE);
require(pool != address(0), "no WFLOW/WETH pool at fee tier");

vm.startBroadcast();
Expand Down Expand Up @@ -86,11 +85,7 @@ contract SwapForWeth is ConfiguredScript {
vm.stopBroadcast();

console.log("swapped %s WFLOW (wei) for %s WETH (wei)", amountIn, received);
console.log(
"min acceptable was %s; account now holds %s WETH (wei)",
minOut,
IERC20(weth).balanceOf(account)
);
console.log("min acceptable was %s; account now holds %s WETH (wei)", minOut, IERC20(weth).balanceOf(account));
}

/// @dev Spot-price-derived minimum WETH out for `amountIn` WFLOW, less
Expand Down
15 changes: 5 additions & 10 deletions solidity/script/UpdatePythPrices.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,10 @@ contract UpdatePythPrices is Script {

IPyth internal constant PYTH = IPyth(0x2880aB155794e7179c9eE2e38200202908C17B43);

string internal constant HERMES_URL =
"https://hermes.pyth.network/v2/updates/price/latest?encoding=hex";
string internal constant FLOW_ID =
"2fb245b9a84554a0f15aa123cbb5f64cd263b59e9a87d80148cbffab50c69f30";
string internal constant ETH_ID =
"ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace";
string internal constant BTC_ID =
"e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43";
string internal constant HERMES_URL = "https://hermes.pyth.network/v2/updates/price/latest?encoding=hex";
string internal constant FLOW_ID = "2fb245b9a84554a0f15aa123cbb5f64cd263b59e9a87d80148cbffab50c69f30";
string internal constant ETH_ID = "ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace";
string internal constant BTC_ID = "e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43";

address internal constant WFLOW_PYUSD_ORACLE = 0xd8848Ccc8beA82046Da0B144844118db17086af4;
address internal constant WETH_PYUSD_ORACLE = 0xD744044044C0Dd0c73BeA440747115674Ebae030;
Expand Down Expand Up @@ -61,8 +57,7 @@ contract UpdatePythPrices is Script {
command[1] = "-fsSL";
command[2] = "--max-time";
command[3] = "30";
command[4] =
string.concat(HERMES_URL, "&ids[]=", FLOW_ID, "&ids[]=", ETH_ID, "&ids[]=", BTC_ID);
command[4] = string.concat(HERMES_URL, "&ids[]=", FLOW_ID, "&ids[]=", ETH_ID, "&ids[]=", BTC_ID);

string memory response = string(vm.ffi(command));
string memory updateDataHex = vm.parseJsonString(response, ".binary.data[0]");
Expand Down
Loading
Loading