Compound is an implementation of MTG and a parachain of Mixin network.
- The user transfers a payment(UTXO) that carries business data to the Mixin network.
- Compound syncs the outputs(UTXO) by parsing the business data(in output.memo)
- Compound dispatchs the business action(included in business data) and processes each action(supply, borrow...)
---
|-cmd
|-config
|-deploy
|-docs
|-core
|-pkg
|-service
|-store
|-worker
|-handler
|-Dockerfile
|-Makefile
|-main.go
- cmd command entry, including start api server and worker and governance tools
- config default config directory
- docs project documents
- core directory of project's models
- pkg project packages that can be exported
- service directory of business codes
- store data repository(data may be stored in database or redis or memory cache)
- worker directory for jobs that processing data in background
- handler just for exported apis
- Dockerfile for deployment
- deploy store configs and tools of deployment
- main.go
- Makefile
# genesis timestamp in second
genesis: 1603382400
location: Asia/Shanghai
db:
dialect: mysql
host: ~
read_host: ~
port: 3306
user: ~
password: ~
database: ~
location: Asia%2FShanghai
debug: true
# It is recommended that each node configure its own price service
price_oracle:
end_point: https://poracle-dev.fox.one
dapp:
num: 7000103159
client_id: ~
session_id: ~
client_secret: ~
pin_token: ~
pin: ""
private_key: ~
group:
# private key shared by all nodes
private_key: ~
# The private key of the node user to sign the data
sign_key: ~
# node admins
admins:
- ~
- ~
- ~
# all nodes
members:
# node id
- client_id: ~
# The public key used by the node to verify the signature
verify_key: ~
# multi-sign threshold
threshold: 2
vote:
asset: 965e5c6e-434c-3fa9-b780-c50f43cd955c
amount: 0.00000001
Rest APIs exported for application layer, including:
/markets //response all markets
/markets/{asset} // response the market info of the specified asset
/liquidities/{address} //response user liquidities
/supplies //response supply datas
/borrows // response borrow datas
/transactions // response transactions
- cashier Processes the pending transfers. prepare for transfering a transaction to Mixin network.
- syncer Syncs the outputs(UTXO) from Mixin network.
- txsender Transfers raw transaction to Mixin network.
- spentsync syncs and updates the transfer state.
- priceoracle Fetches a price and put the price on the chain.
- payee processes outputs and dispatches business actions.
- borrow handles the borrow action event.
- supply handles the supply action event.
- pledge handles the pledge action event.
- unpledge handles the unpledge action event.
- redeem handles the redeem action event.
- repay handles the repay action event.
- liquidation handles the liquidation action event
- proposal handles and dispatches the proposal actions, include: adding market, updating market, closing or opening market, adding or removing allowlist, withdraw
- price handles the price protocal action event.
Close the market when the price of a certain market is abnormal.
- When the price of a market is maliciously attacked, managers have the right to execute the
close-market
order and apply for a closed-market vote. If the request is approved, the market will be closed. - Trades are prohibited in closed markets.
- However, as long as there are closed markets, liquidation of all markets will be prohibited, because liquidation will affect the liquidity of all market accounts of users.
-
Interest rate model is The core implementation of compound protocol.
-
Borrow balance user borrow balance contains borrow principal and borrow interest.
balance = borrow.principal * market.borrow_index / borrow.interest_index
-
Accrue interest Accruing interest only occurs when there is a behavior that causes changes in market transaction data, such as supply, borrow, pledge, unpledge, redeem, repay, price updating. And Only calculated once in the same block.
blockNumberPrior := market.BlockNumber
blockNum, e := s.blockSrv.GetBlock(ctx, time)
if e != nil {
return e
}
blockDelta := blockNum - blockNumberPrior
if blockDelta > 0 {
borrowRate, e := s.curBorrowRatePerBlockInternal(ctx, market)
if e != nil {
return e
}
if market.BorrowIndex.LessThanOrEqual(decimal.Zero) {
market.BorrowIndex = borrowRate
}
timesBorrowRate := borrowRate.Mul(decimal.NewFromInt(blockDelta))
interestAccumulated := market.TotalBorrows.Mul(timesBorrowRate)
totalBorrowsNew := interestAccumulated.Add(market.TotalBorrows)
totalReservesNew := interestAccumulated.Mul(market.ReserveFactor).Add(market.Reserves)
borrowIndexNew := market.BorrowIndex.Add(timesBorrowRate.Mul(market.BorrowIndex))
market.BlockNumber = blockNum
market.TotalBorrows = totalBorrowsNew.Truncate(16)
market.Reserves = totalReservesNew.Truncate(16)
market.BorrowIndex = borrowIndexNew.Truncate(16)
}