Supply
Learn how to supply through Morpho, onchain via a smart contract & offchain via ethers.js.
Morpho AaveV2 Optimizer & Morpho CompoundV2 Optimizer allow anyone to supply to any open market and potentially benefit from higher yields via automatic matching, offchain through Etherscan or with ethers.js, or onchain using a smart contract. Here are concrete examples 👇
Morpho AaveV2 Optimizer​
- Solidity
- ethers.js
// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.16;
import {IMorpho} from "./interfaces/IMorpho.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH9 {
function deposit() external payable;
}
contract MorphoAaveV2Supplier {
address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address public constant AWETH = 0x030bA81f1c18d280636F32af80b9AAd02Cf0854e;
address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address public constant ADAI = 0x028171bCA77440897B824Ca71D1c56caC55b68A3;
address public constant MORPHO = 0x777777c9898D384F785Ee44Acfe945efDFf5f3E0;
function _supplyERC20(
address _aToken,
address _underlying,
uint256 _amount
) internal {
IERC20(_underlying).approve(MORPHO, _amount);
IMorpho(MORPHO).supply(
_aToken,
address(this), // the address of the user you want to supply on behalf of
_amount
);
}
function supplyDAI(uint256 _amount) public {
_supplyERC20(
ADAI, // the DAI market, represented by the aDAI ERC20 token
DAI,
_amount
);
}
function supplyETH() public payable {
// first wrap ETH into WETH
IWETH9(WETH).deposit{value: msg.value}();
_supplyERC20(
AWETH, // the WETH market, represented by the aWETH ERC20 token
WETH,
msg.value
);
}
}
import ethers from "ethers";
const signer = new ethers.Wallet(
process.env.PRIVATE_KEY,
new ethers.providers.JsonRpcBatchProvider(process.env.RPC_URL)
);
const signerAddress = await signer.getAddress();
const aWethAddress = "0x030bA81f1c18d280636F32af80b9AAd02Cf0854e";
const aDaiAddress = "0x028171bCA77440897B824Ca71D1c56caC55b68A3";
const daiDecimals = 18;
const weth = new ethers.Contract(
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
[
"function deposit() external payable",
"function approve(address, uint256) external returns (bool)",
],
signer
);
const dai = new ethers.Contract(
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
["function approve(address, uint256) external returns (bool)"],
signer
);
const morpho = new ethers.Contract(
"0x777777c9898d384f785ee44acfe945efdff5f3e0",
[
"function supply(address, address, uint256) external",
"function supply(address, address, uint256, uint256) external",
],
signer
);
async function supplyERC20(aTokenAddress, underlying, amount) {
await underlying.approve(morpho.address, amount);
await morpho.supply(
aTokenAddress,
signerAddress, // the address of the user you want to supply on behalf of
amount
);
}
async function supplyDAI(amount) {
return supplyERC20(
aDaiAddress, // the DAI market, represented by the aDAI ERC20 token
dai,
amount
);
}
async function supplyETH(amount) {
// first wrap ETH into WETH
await weth.deposit({ value: amount });
return supplyERC20(
aWethAddress, // the WETH market, represented by the cETH ERC20 token
weth,
amount
);
}
// supplyDAI(ethers.utils.parseUnits("100", daiDecimals));
// supplyETH(ethers.utils.parseEther(1));
Morpho CompoundV2 Optimizer​
- Solidity
- ethers.js
// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.16;
import {IMorpho} from "@morpho-org/morpho-core-v1/contracts/compound/interfaces/IMorpho.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH9 {
function deposit() external payable;
}
contract MorphoCompoundSupplier {
address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address public constant CETH = 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5;
address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address public constant CDAI = 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643;
address public constant MORPHO = 0x8888882f8f843896699869179fB6E4f7e3B58888;
function _supplyERC20(
address _cToken,
address _underlying,
uint256 _amount
) internal {
IERC20(_underlying).approve(MORPHO, _amount);
IMorpho(MORPHO).supply(
_cToken,
address(this), // the address of the user you want to supply on behalf of
_amount
);
}
function supplyDAI(uint256 _amount) public {
_supplyERC20(
CDAI, // the DAI market, represented by the cDAI ERC20 token
DAI,
_amount
);
}
function supplyETH() public payable {
// first wrap ETH into WETH
IWETH9(WETH).deposit{value: msg.value}();
_supplyERC20(
CETH, // the WETH market, represented by the cETH ERC20 token
WETH,
msg.value
);
}
}
import ethers from "ethers";
const signer = new ethers.Wallet(
process.env.PRIVATE_KEY,
new ethers.providers.JsonRpcBatchProvider(process.env.RPC_URL)
);
const signerAddress = await signer.getAddress();
const cEthAddress = "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5";
const cDaiAddress = "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643";
const daiDecimals = 18;
const weth = new ethers.Contract(
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
[
"function deposit() external payable",
"function approve(address, uint256) external returns (bool)",
],
signer
);
const dai = new ethers.Contract(
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
["function approve(address, uint256) external returns (bool)"],
signer
);
const morpho = new ethers.Contract(
"0x8888882f8f843896699869179fB6E4f7e3B58888",
[
"function supply(address, address, uint256) external",
"function supply(address, address, uint256, uint256) external",
],
signer
);
async function supplyERC20(cTokenAddress, underlying, amount) {
await underlying.approve(morpho.address, amount);
await morpho.supply(
cTokenAddress,
signerAddress, // the address of the user you want to supply on behalf of
amount
);
}
async function supplyDAI(amount) {
return supplyERC20(
cDaiAddress, // the DAI market, represented by the cDAI ERC20 token
dai,
amount
);
}
async function supplyETH(amount) {
// first wrap ETH into WETH
await weth.deposit({ value: amount });
return supplyERC20(
cEthAddress, // the WETH market, represented by the cETH ERC20 token
weth,
amount
);
}
// supplyDAI(ethers.utils.parseUnits("100", daiDecimals));
// supplyETH(ethers.utils.parseEther(1));
ERC4626 Vaults​
Morpho's vaults are another way to interact with Morpho according to the ERC4626 standard.
- Solidity
- ethers.js
// SPDX-License-Identifier: GNU AGPLv3
pragma solidity ^0.8.13;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ISupplyVault} from "@morpho-org/morpho-tokenized-vaults/src/aave-v2/interfaces/ISupplyVault.sol";
contract MorphoAaveV2VaultSupplier {
address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address public constant MC_DAI = 0xd99D793B8FDaE42C1867293C172b9CBBD3ea49FF;
address public constant MCH_DAI =
0x5CBead740564A2173983E48f94F36357C1954EAE;
function deposit(uint256 _amount) internal {
IERC20(DAI).approve(MC_DAI, _amount);
ISupplyVault(MC_DAI).deposit(
_amount,
address(this) // the address of the user you want to supply on behalf of
);
}
function depositHarvest(uint256 _amount) internal {
IERC20(DAI).approve(MCH_DAI, _amount);
ISupplyHarvestVault(MCH_DAI).deposit(
_amount,
address(this) // the address of the user you want to supply on behalf of
);
}
/// REWARDS ///
function claimRewards() {
ISupplyVault(MC_DAI).claimRewards(address(this));
}
function harvest() {
ISupplyVault(MCH_DAI).harvest();
}
}
import ethers from "ethers";
const signer = new ethers.Wallet(
process.env.PRIVATE_KEY,
new ethers.providers.JsonRpcBatchProvider(process.env.RPC_URL)
);
const daiDecimals = 18;
const dai = new ethers.Contract(
"0x6B175474E89094C44Da98b954EedeAC495271d0F",
DAIAbi,
signer
);
const mcDai = new ethers.Contract(
"0xd99D793B8FDaE42C1867293C172b9CBBD3ea49FF",
SupplyVaultAbi,
signer
);
const mchDai = new ethers.Contract(
"0x5CBead740564A2173983E48f94F36357C1954EAE",
SupplyHarvestVaultAbi,
signer
);
const amount = ethers.utils.parseUnits("100", daiDecimals);
dai.approve(mcDai.address, amount);
mcDai.deposit(amount, signer.address);
dai.approve(mchDai.address, amount);
mchDai.deposit(amount, signer.address);
/// REWARDS ///
mcDai.claimRewards(signer.address);
mchDai.harvest();