88mph Docs v4
  • Introduction
  • Disclaimer
  • Getting started
    • Fixed yield rate
    • Yield tokens
    • Risk mitigation
  • MPH, veMPH and Gauges
    • MPH Tokenomics
    • veMPH
      • Understanding veMPH
      • Using veMPH
    • Gauges
  • Developer docs
    • Integration guide
    • Smart contract architecture
    • Smart contract references
      • DInterest
      • DInterestLens
      • ZeroCouponBond
    • Deployment guide
    • Audits / Security
    • Smart contract addresses
    • REST API
    • Ethereum subgraph
    • Ethereum Rinkeby subgraph
    • Fantom subgraph
    • Avalanche subgraph
    • Polygon subgraph
  • Governance
  • Governance
    • Proposals
  • Forum
  • Vote
  • Governance guidelines
  • Governance treasury
  • Grants & Funding
  • Resources
    • Docs v3
    • Docs v2
  • Changelog
Powered by GitBook
On this page
  • Smart contract
  • Creating a deposit
  • Withdrawing a deposit
  • Calculate Interest Amount
  • Withdrawing vested MPH rewards
  • Buying yield tokens
  • Zero coupon bonds
  • REST API
  • Example response
  • Deployment
  1. Developer docs

Integration guide

PreviousGaugesNextSmart contract architecture

Last updated 2 years ago

Smart contract

To interact with an 88mph pool, you will mostly call the pool's DInterest contract. You can find the source code on .

Creating a deposit

Creating a deposit has two steps:

  1. Give ERC-20 approval to the DInterest contract, the amount of which is at least the deposit amount.

  2. Call DInterest::deposit()

Once an account makes a deposit, the account will also receive vested MPH rewards.

Example

DInterest pool = DInterest(0xdead);
ERC20 token = ERC20(0x6b175474e89094c44da98b954eedeac495271d0f); // DAI
uint256 depositAmount = 3 * 10 ** 18; // 3 DAI
uint256 maturationTimestamp = now + 365 days;
​require(token.approve(address(pool), depositAmount));
// deposit returns the ID of the deposit
uint64 depositID = pool.deposit(depositAmount, maturationTimestamp);

Trace and map out all the contract interactions with this .

Withdrawing a deposit

Withdrawing a deposit has the following steps:

  1. Call DInterest::withdraw()

Set virtualTokenAmount to type(uint256).max to withdraw all funds from the deposit, otherwise set it to some proportion of getDeposit(depositID).virtualTokenTotalSupply to do a partial withdrawal. An easy way to determine the value for this field is that after maturation, virtualTokenAmount equals the amount of underlying tokens that will be withdrawn.

Set early to true if withdrawing before maturation, false if withdrawing after maturation.

Example

DInterest pool = DInterest(0xdead);
uint64 depositID = 10;
uint256 virtualTokenAmount = type(uint256).max; // withdraw all funds
bool early = false; // withdrawing after maturation​
pool.withdraw(depositID, virtualTokenAmount, early);

Calculate Interest Amount

If you want to know the interest you'll earn on a 100 DAI deposit for 1 year, the function call would look like calculateInterestAmount(100*1e18, 31556952) where 100*1e18 is 100 DAI in wei and 31556952 is the number of seconds in a year.

Withdrawing vested MPH rewards

The vesting streams are represented using 1-indexed ERC-721 NFTs, so that they are easily transferrable.

In order to withdraw vested MPH, you need to call Vesting02::withdraw(uint256 vestID). You need the index of a vesting NFT, vestID, in order to withdraw the MPH. You can obtain this value using the Vesting02::depositIDToVestID mapping using the pool address and deposit ID.

Example

Vesting02 vesting = Vesting02(0xdead);
uint64 vestID = 10;​ // msg.sender needs to own the vesting NFT
vesting.withdraw(vestID);

Buying yield tokens

Buying yield tokens takes two steps:

  1. Approve deposit tokens to the DInterest contract, the amount of which should be at least the cost of the bond.

  2. Call DInterest::fund() with the ID of the deposit to buy yield tokens from and the amount to pay.

Note that if the amount to pay is greater than the value of the available yield tokens, all of the available yield tokens will be purchased.

Example

DInterest pool = DInterest(0xdead);
ERC20 token = ERC20(0x6b175474e89094c44da98b954eedeac495271d0f); // DAI​
uint64 depositID = 5;
uint256 payAmount = 3 * 10**18; // 3 DAI
require(token.approve(address(pool), payAmount));
uint64 fundingID = pool.fund(depositID, payAmount);

Zero coupon bonds

Minting a zero coupon bond

ZeroCouponBond bond = ZeroCouponBond(0xdead);
ERC20 token = ERC20(0x6b175474e89094c44da98b954eedeac495271d0f); // DAI
uint256 depositAmount = 3 * 10**18; // 3 DAI
require(token.approve(address(bond), depositAmount));
​// mint returns the amount of zero coupon bonds minted
// which can be 1-for-1 redeemed for the underlying token
// at maturation
uint256 mintedZCBAmount = bond.mint(depositAmount);

Redeeming zero coupon bonds for their face value

ZeroCouponBond bond = ZeroCouponBond(0xdead);​
uint256 redeemAmount = 30 * (10 ** 18); // 30 DAI
// setting this to true will withdraw the ZCB's deposit
// from the 88mph pool if it hasn't been done yet
// which will increase the gas cost but also
// ensures that the redemption succeeds
bool withdrawDepositIfNeeded = true;
bond.redeem(redeemAmount, withdrawDepositIfNeeded);

REST API

Example response

[  {    "address": "0xb1abaac351e06d40441cf2cd97f6f0098e6473f2",     "token": "0x5b5cfe992adac0c9d48e05854b2d91c73a003858",     "tokenSymbol": "CRV:HUSD",     "protocol": "Harvest",     "oneYearInterestRate": "3.6621277863445296",     "mphAPY": "60.8988450243270707253",     "totalValueLockedInToken": "1548211.678555032702255836",     "totalValueLockedInUSD": "1548211.678555032702255836"   },  ...]

Deployment

Notes:

Function on the DInterest contract to call can be found .

The returned value is the amount of DAI, in wei, you'd earn in fixed-rate interest before protocol fees are taken into account. To account for the fee, you'll need to call getInterestFeeAmount() on the .

Once you have both the interest amount (before fees) and the fee amount, subtract the two values to get the amount of interest earned by the depositor after fees. Divide that value by the original deposit amount to get the APR (some additional math is needed for deposit length of less than a year). Here is of how we do this in our frontend, which calculates the APR for a 10,000 token deposit for 30 days.

Each deposit yields vested MPH rewards to the user. This is handled by the . The vesting is linear and continuous, and is done over the deposit period. If a deposit is withdrawn earlier than the maturation date, the remaining vested rewards are forfeited.

We offer a REST API for fetching basic info of 88mph pools. The endpoint is at . The only supported method is GET.

Read

The mainnet contract addresses are available here and the rinkeby here /

Rinkeby subgraph:

our GitHub
deposit transaction example
here
feeModel contract
an example
Vesting02 contract
https://api.88mph.app/v3/pools
DEPLOY_README.md
https://github.com/88mphapp/88mph-contracts/tree/v3/deployments/mainnet
https://github.com/88mphapp/88mph-contracts/tree/v3/deployments/rinkeby
https://github.com/88mphapp/88mph-contracts/blob/v3/deployments-exported/rinkeby.json
https://thegraph.com/legacy-explorer/subgraph/bacon-labs/eighty-eight-mph-v3-rinkeby