Top Related Projects
Aave Protocol Version 1.0 - Decentralized Lending Pools
š¦ š¦ š¦ Core smart contracts of Uniswap v3
Quick Overview
The Compound Protocol is an algorithmic, autonomous interest rate protocol built for developers, enabling the creation of open financial applications. It allows users to supply assets to earn interest or borrow assets against collateral, with interest rates automatically adjusted based on supply and demand.
Pros
- Decentralized and permissionless lending and borrowing
- Automatic interest rate adjustments based on market conditions
- High liquidity and efficient capital allocation
- Composability with other DeFi protocols
Cons
- Smart contract risk and potential vulnerabilities
- Reliance on price oracles for collateral valuation
- Complexity for non-technical users
- Potential for liquidation in volatile market conditions
Code Examples
- Supplying assets to the Compound protocol:
function supplyEthToCompound(address payable _cEtherContract) public payable returns (bool) {
CEth cToken = CEth(_cEtherContract);
cToken.mint{value: msg.value}();
return true;
}
- Borrowing assets from the Compound protocol:
function borrowErc20FromCompound(
address _cTokenAddress,
uint256 _borrowAmount
) public returns (uint256) {
CToken cToken = CToken(_cTokenAddress);
uint256 error = cToken.borrow(_borrowAmount);
require(error == 0, "Borrow failed");
return error;
}
- Repaying a borrowed asset:
function repayBorrow(
address _cTokenAddress,
uint256 _repayAmount
) public returns (bool) {
CToken cToken = CToken(_cTokenAddress);
IERC20 underlying = IERC20(cToken.underlying());
underlying.approve(_cTokenAddress, _repayAmount);
uint256 error = cToken.repayBorrow(_repayAmount);
require(error == 0, "Repay failed");
return true;
}
Getting Started
To interact with the Compound Protocol:
- Install the required dependencies:
npm install @compound-finance/compound-js ethers
- Import and initialize the Compound.js library:
const Compound = require('@compound-finance/compound-js');
const ethers = require('ethers');
const compound = new Compound(window.ethereum);
- Connect to the Ethereum network and interact with the protocol:
async function supplyEth(amount) {
const tx = await compound.supply(Compound.ETH, amount);
await tx.wait(1); // wait for one confirmation
console.log('Supply successful');
}
Competitor Comparisons
Aave Protocol Version 1.0 - Decentralized Lending Pools
Pros of Aave Protocol
- More flexible interest rate model with stable and variable rates
- Supports flash loans, enabling advanced DeFi strategies
- Wider range of supported assets and collateral types
Cons of Aave Protocol
- Higher complexity in smart contract architecture
- Potentially higher gas costs due to additional features
- Newer protocol with less battle-testing compared to Compound
Code Comparison
Aave Protocol:
function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf) external override whenNotPaused {
DataTypes.ReserveData storage reserve = _reserves[asset];
_executeBorrow(ExecuteBorrowParams(asset, msg.sender, onBehalfOf, amount, interestRateMode, referralCode, true));
}
Compound Protocol:
function borrow(uint amount) external returns (uint) {
return borrowInternal(amount);
}
function borrowInternal(uint amount) internal nonReentrant returns (uint) {
accrueInterest();
borrowFresh(msg.sender, amount);
return uint(Error.NO_ERROR);
}
The Aave Protocol code snippet shows a more feature-rich borrow function with additional parameters, while the Compound Protocol code is simpler but requires separate internal functions for borrowing logic.
š¦ š¦ š¦ Core smart contracts of Uniswap v3
Pros of v3-core
- Improved capital efficiency with concentrated liquidity
- More flexible fee structure with multiple fee tiers
- Advanced range order functionality for precise liquidity provision
Cons of v3-core
- Higher complexity for liquidity providers
- Potential for increased gas costs due to complex operations
- Less intuitive for casual users compared to simpler AMM models
Code Comparison
compound-protocol:
function mint(uint mintAmount) external returns (uint) {
(uint err,) = mintInternal(mintAmount);
return err;
}
v3-core:
function mint(
address recipient,
int24 tickLower,
int24 tickUpper,
uint128 amount,
bytes calldata data
) external override lock returns (uint256 amount0, uint256 amount1) {
require(amount > 0);
// ... (additional logic)
}
The v3-core mint
function demonstrates increased complexity with more parameters and granular control over liquidity provision, while the compound-protocol mint
function is simpler but less flexible.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Compound Protocol
The Compound Protocol is an Ethereum smart contract for supplying or borrowing assets. Through the cToken contracts, accounts on the blockchain supply capital (Ether or ERC-20 tokens) to receive cTokens or borrow assets from the protocol (holding other assets as collateral). The Compound cToken contracts track these balances and algorithmically set interest rates for borrowers.
Before getting started with this repo, please read:
- The Compound Whitepaper, describing how Compound works
- The Compound Protocol Specification, explaining in plain English how the protocol operates
For questions about interacting with Compound, please visit our Discord server.
For security concerns, please visit https://compound.finance/security or email security@compound.finance.
Contributing
Contributing to the Compound protocol is a bit different than most open-source projects -- check out the community guide on Contributing.
Contracts
We detail a few of the core contracts in the Compound protocol.
- CToken, CErc20 and CEther
- The Compound cTokens, which are self-contained borrowing and lending contracts. CToken contains the core logic and CErc20 and CEther add public interfaces for Erc20 tokens and ether, respectively. Each CToken is assigned an interest rate and risk model (see InterestRateModel and Comptroller sections), and allows accounts to *mint* (supply capital), *redeem* (withdraw capital), *borrow* and *repay a borrow*. Each CToken is an ERC-20 compliant token where balances represent ownership of the market.
- Comptroller
- The risk model contract, which validates permissible user actions and disallows actions if they do not fit certain risk parameters. For instance, the Comptroller enforces that each borrowing user must maintain a sufficient collateral balance across all cTokens.
- Follow the existing naming schema (ControllerGX)
- Update the scenario runner in scenario/src/Builder/ComptrollerImplBuilder.ts
- Create unit tests and fork simulations as necessary
- Call
npx saddle deploy Comptroller -n mainnet
to deploy to mainnet and generate new ABI - The ABI can also be generated by deploying to mainnet in a fork simulation
- Call
node script/comptroller-abi
to merge the new Comptroller ABI with the Unitroller ABI - Ensure that commit contains new generated Comptroller ABI
-
Updating the Comptroller
- Comp
- The Compound Governance Token (COMP). Holders of this token have the ability to govern the protocol via the governor contract.
- Governor Alpha
- The administrator of the Compound timelock contract. Holders of Comp token may create and vote on proposals which will be queued into the Compound timelock and then have effects on Compound cToken and Comptroller contracts. This contract may be replaced in the future with a beta version.
- InterestRateModel
- Contracts which define interest rate models. These models algorithmically determine interest rates based on the current utilization of a given market (that is, how much of the supplied assets are liquid versus borrowed).
- Careful Math
- Library for safe math operations.
- ErrorReporter
- Library for tracking error codes and failure conditions.
- Exponential
- Library for handling fixed-point decimal numbers.
- SafeToken
- Library for safely handling Erc20 interaction.
- WhitePaperInterestRateModel
- Initial interest rate model, as defined in the Whitepaper. This contract accepts a base rate and slope parameter in its constructor.
Installation
To run compound, pull the repository from GitHub and install its dependencies. You will need yarn or npm installed.
git clone https://github.com/compound-finance/compound-protocol
cd compound-protocol
yarn install --lock-file # or `npm install`
REPL
The Compound Protocol has a simple scenario evaluation tool to test and evaluate scenarios which could occur on the blockchain. This is primarily used for constructing high-level integration tests. The tool also has a REPL to interact with local the Compound Protocol (similar to truffle console
).
yarn repl -n development
yarn repl -n rinkeby
> Read CToken cBAT Address
Command: Read CToken cBAT Address
AddressV<val=0xAD53863b864AE703D31b819d29c14cDA93D7c6a6>
You can read more about the scenario runner in the Scenario Docs on steps for using the repl.
Testing
Jest contract tests are defined under the tests directory. To run the tests run:
yarn test
Integration Specs
There are additional tests under the spec/scenario folder. These are high-level integration tests based on the scenario runner depicted above. The aim of these tests is to be highly literate and have high coverage in the interaction of contracts.
Formal Verification Specs
The Compound Protocol has a number of formal verification specifications, powered by Certora. You can find details in the spec/formal folder. The Certora Verification Language (CVL) files included are specifications, which when with the Certora CLI tool, produce formal proofs (or counter-examples) that the code of a given contract exactly matches that specification.
Code Coverage
To run code coverage, run:
yarn coverage
Linting
To lint the code, run:
yarn lint
Docker
To run in docker:
# Build the docker image
docker build -t compound-protocol .
# Run a shell to the built image
docker run -it compound-protocol /bin/sh
From within a docker shell, you can interact locally with the protocol via ganache and truffle:
/compound-protocol > yarn console -n goerli
Using network goerli https://goerli-eth.compound.finance
Saddle console on network goerli https://goerli-eth.compound.finance
Deployed goerli contracts
comptroller: 0x627EA49279FD0dE89186A58b8758aD02B6Be2867
comp: 0xfa5E1B628EFB17C024ca76f65B45Faf6B3128CA5
governorAlpha: 0x8C3969Dd514B559D78135e9C210F2F773Feadf21
maximillion: 0x73d3F01b8aC5063f4601C7C45DA5Fdf1b5240C92
priceOracle: 0x9A536Ed5C97686988F93C9f7C2A390bF3B59c0ec
priceOracleProxy: 0xd0c84453b3945cd7e84BF7fc53BfFd6718913B71
timelock: 0x25e46957363e16C4e2D5F2854b062475F9f8d287
unitroller: 0x627EA49279FD0dE89186A58b8758aD02B6Be2867
> await comp.methods.totalSupply().call()
'10000000000000000000000000'
Console
After you deploy, as above, you can run a truffle console with the following command:
yarn console -n goerli
This command will start a saddle console conencted to Goerli testnet (see Saddle README):
Using network goerli https://goerli.infura.io/v3/e1a5d4d2c06a4e81945fca56d0d5d8ea
Saddle console on network goerli https://goerli.infura.io/v3/e1a5d4d2c06a4e81945fca56d0d5d8ea
Deployed goerli contracts
comptroller: 0x627EA49279FD0dE89186A58b8758aD02B6Be2867
comp: 0xfa5E1B628EFB17C024ca76f65B45Faf6B3128CA5
governorAlpha: 0x8C3969Dd514B559D78135e9C210F2F773Feadf21
maximillion: 0x73d3F01b8aC5063f4601C7C45DA5Fdf1b5240C92
priceOracle: 0x9A536Ed5C97686988F93C9f7C2A390bF3B59c0ec
priceOracleProxy: 0xd0c84453b3945cd7e84BF7fc53BfFd6718913B71
timelock: 0x25e46957363e16C4e2D5F2854b062475F9f8d287
unitroller: 0x627EA49279FD0dE89186A58b8758aD02B6Be2867
> await comp.methods.totalSupply().call()
'10000000000000000000000000'
Deploying a CToken from Source
Note: you will need to set ~/.ethereum/<network>
with your private key or assign your private key to the environment variable ACCOUNT
.
Note: for all sections including Etherscan verification, you must set the ETHERSCAN_API_KEY
to a valid API Key from Etherscan.
To deploy a new cToken, you can run the token:deploy
. command, as follows. If you set VERIFY=true
, the script will verify the token on Etherscan as well. The JSON here is the token config JSON, which should be specific to the token you wish to list.
npx saddle -n rinkeby script token:deploy '{
"underlying": "0x577D296678535e4903D59A4C929B718e1D575e0A",
"comptroller": "$Comptroller",
"interestRateModel": "$Base200bps_Slope3000bps",
"initialExchangeRateMantissa": "2.0e18",
"name": "Compound Kyber Network Crystal",
"symbol": "cKNC",
"decimals": "8",
"admin": "$Timelock"
}'
If you only want to verify an existing token an Etherscan, make sure ETHERSCAN_API_KEY
is set and run token:verify
with the first argument as the token address and the second as the token config JSON:
npx saddle -n rinkeby script token:verify 0x19B674715cD20626415C738400FDd0d32D6809B6 '{
"underlying": "0x577D296678535e4903D59A4C929B718e1D575e0A",
"comptroller": "$Comptroller",
"interestRateModel": "$Base200bps_Slope3000bps",
"initialExchangeRateMantissa": "2.0e18",
"name": "Compound Kyber Network Crystal",
"symbol": "cKNC",
"decimals": "8",
"admin": "$Timelock"
}'
Finally, to see if a given deployment matches this version of the Compound Protocol, you can run token:match
with a token address and token config:
npx saddle -n rinkeby script token:match 0x19B674715cD20626415C738400FDd0d32D6809B6 '{
"underlying": "0x577D296678535e4903D59A4C929B718e1D575e0A",
"comptroller": "$Comptroller",
"interestRateModel": "$Base200bps_Slope3000bps",
"initialExchangeRateMantissa": "2.0e18",
"name": "Compound Kyber Network Crystal",
"symbol": "cKNC",
"decimals": "8",
"admin": "$Timelock"
}'
Deploying a CToken from Docker Build
To deploy a specific version of the Compound Protocol, you can use the token:deploy
script through Docker:
docker run --env ETHERSCAN_API_KEY --env VERIFY=true --env ACCOUNT=0x$(cat ~/.ethereum/rinkeby) compoundfinance/compound-protocol:latest npx saddle -n rinkeby script token:deploy '{
"underlying": "0x577D296678535e4903D59A4C929B718e1D575e0A",
"comptroller": "$Comptroller",
"interestRateModel": "$Base200bps_Slope3000bps",
"initialExchangeRateMantissa": "2.0e18",
"name": "Compound Kyber Network Crystal",
"symbol": "cKNC",
"decimals": "8",
"admin": "$Timelock"
}'
To match a deployed contract against a given version of the Compound Protocol, you can run token:match
through Docker, passing a token address and config:
docker run --env ACCOUNT=0x$(cat ~/.ethereum/rinkeby) compoundfinance/compound-protocol:latest npx saddle -n rinkeby script token:match 0xF1BAd36CB247C82Cb4e9C2874374492Afb50d565 '{
"underlying": "0x577D296678535e4903D59A4C929B718e1D575e0A",
"comptroller": "$Comptroller",
"interestRateModel": "$Base200bps_Slope3000bps",
"initialExchangeRateMantissa": "2.0e18",
"name": "Compound Kyber Network Crystal",
"symbol": "cKNC",
"decimals": "8",
"admin": "$Timelock"
}'
Discussion
For any concerns with the protocol, open an issue or visit us on Discord to discuss.
For security concerns, please email security@compound.finance.
ĆĀ© Copyright 2020, Compound Labs
Top Related Projects
Aave Protocol Version 1.0 - Decentralized Lending Pools
š¦ š¦ š¦ Core smart contracts of Uniswap v3
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot