Skip to content

Commit fc85f3b

Browse files
committed
feat: morpho example supplying/repaying from rollup
1 parent 996ec1f commit fc85f3b

File tree

2 files changed

+498
-0
lines changed

2 files changed

+498
-0
lines changed

src/apps/Morpho.sol

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.13;
3+
4+
import {IMorpho, MarketParams} from "../interfaces/IMorpho.sol";
5+
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
6+
import {SignetStd} from "../SignetStd.sol";
7+
import {RollupOrders} from "zenith/src/orders/RollupOrders.sol";
8+
9+
// Rollup contract that uses a host chain Morpho shortcut to supply collateral
10+
// and repay loans on behalf of the rollup user.
11+
contract UseMorpho is SignetStd {
12+
address immutable shortcut;
13+
14+
address immutable hostLoanToken;
15+
address immutable hostCollateralToken;
16+
17+
IERC20 immutable loanToken;
18+
IERC20 immutable collateralToken;
19+
20+
constructor(address _shortcut, address _hostLoan, address _hostCollateral) SignetStd() {
21+
shortcut = _shortcut;
22+
hostLoanToken = _hostLoan;
23+
hostCollateralToken = _hostCollateral;
24+
25+
if (_hostLoan == HOST_WETH) {
26+
loanToken = WETH;
27+
} else if (_hostLoan == HOST_WBTC) {
28+
loanToken = WBTC;
29+
} else if (_hostLoan == HOST_USDC || _hostLoan == HOST_USDT) {
30+
loanToken = WUSD;
31+
} else {
32+
revert("Unsupported loan token");
33+
}
34+
35+
loanToken.approve(address(ORDERS), type(uint256).max);
36+
collateralToken.approve(address(ORDERS), type(uint256).max);
37+
}
38+
39+
function supply(uint256 amount) external {
40+
if (amount > 0) {
41+
collateralToken.transferFrom(msg.sender, address(this), amount);
42+
}
43+
44+
// the amount is whatever our current balance is
45+
amount = collateralToken.balanceOf(address(this));
46+
47+
RollupOrders.Input[] memory inputs = new RollupOrders.Input[](1);
48+
inputs[0] = makeInput(address(collateralToken), amount);
49+
50+
// The output pays the collateral token to the shortcut,
51+
// Then calls the shortcut to supply the collateral.
52+
RollupOrders.Output[] memory outputs = new RollupOrders.Output[](2);
53+
outputs[0] = makeHostOutput(address(hostCollateralToken), amount, shortcut);
54+
// call shortcut
55+
outputs[1] = makeHostOutput(shortcut, 0, address(this));
56+
57+
ORDERS.initiate(
58+
block.timestamp, // no deadline
59+
inputs,
60+
outputs
61+
);
62+
}
63+
64+
function repay(uint256 amount) external {
65+
if (amount > 0) {
66+
loanToken.transferFrom(msg.sender, address(this), amount);
67+
}
68+
69+
// the amount is whatever our current balance is
70+
amount = loanToken.balanceOf(address(this));
71+
72+
RollupOrders.Input[] memory inputs = new RollupOrders.Input[](1);
73+
inputs[0] = makeInput(address(loanToken), amount);
74+
75+
// The output pays the loan token to the shortcut,
76+
// Then calls the shortcut to repay the loan.
77+
RollupOrders.Output[] memory outputs = new RollupOrders.Output[](2);
78+
outputs[0] = makeHostOutput(address(hostLoanToken), amount, shortcut);
79+
outputs[1] = makeHostOutput(shortcut, 0, address(this)); // call shortcut
80+
81+
ORDERS.initiate(
82+
block.timestamp, // no deadline
83+
inputs,
84+
outputs
85+
);
86+
}
87+
}
88+
89+
// This contract should be deployed on the host chain. It is used as a shortcut
90+
// to supply collateral to Morpho and can be invoked by the rollup via an Order.
91+
contract HostMorphoShortcut {
92+
IMorpho immutable morpho;
93+
94+
// This is an unrolled MarketParams struct.
95+
IERC20 immutable loanToken;
96+
IERC20 immutable collateralToken;
97+
address immutable oracle;
98+
address immutable irm;
99+
uint256 immutable lltv;
100+
101+
address immutable onBehalf;
102+
103+
constructor(IMorpho _morpho, MarketParams memory _params, address _onBehalf) {
104+
morpho = _morpho;
105+
106+
loanToken = IERC20(_params.loanToken);
107+
collateralToken = IERC20(_params.collateralToken);
108+
oracle = _params.oracle;
109+
irm = _params.irm;
110+
lltv = _params.lltv;
111+
112+
onBehalf = _onBehalf;
113+
114+
collateralToken.approve(address(_morpho), type(uint256).max);
115+
}
116+
117+
fallback() external {
118+
MarketParams memory params;
119+
params.loanToken = address(loanToken);
120+
params.collateralToken = address(collateralToken);
121+
params.oracle = oracle;
122+
params.irm = irm;
123+
params.lltv = lltv;
124+
125+
uint256 loanTokenBalance = loanToken.balanceOf(address(this));
126+
uint256 collateralTokenBalance = collateralToken.balanceOf(address(this));
127+
128+
// If we have loan tokens, we are repaying a loan.
129+
if (loanTokenBalance > 0) {
130+
morpho.repay(params, loanTokenBalance, 0, onBehalf, "");
131+
return;
132+
}
133+
134+
// If we have collateral tokens, we are supplying collateral.
135+
if (collateralTokenBalance > 0) {
136+
morpho.supplyCollateral(params, collateralTokenBalance, onBehalf, "");
137+
138+
// borrow and send to rollup?
139+
140+
return;
141+
}
142+
143+
revert("No tokens received");
144+
}
145+
}

0 commit comments

Comments
 (0)