-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add Compound Lens The Compound Lens is a view contract Compound smart contracts that provides the data dApps need to stay hydrated. Specifically, we wrap the main data that our dApp is asking for. There's probably more bundling we could do, but this already reduces the raw number of calls by 98% (from about 10/s to about 0.2/s). * Add CompoundLens deployments
- Loading branch information
Showing
7 changed files
with
195 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
pragma solidity ^0.5.16; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import "../CErc20.sol"; | ||
import "../CToken.sol"; | ||
import "../Comptroller.sol"; | ||
import "../EIP20Interface.sol"; | ||
|
||
contract CompoundLens { | ||
struct CTokenMetadata { | ||
address cToken; | ||
uint exchangeRateCurrent; | ||
uint supplyRatePerBlock; | ||
uint borrowRatePerBlock; | ||
uint reserveFactorMantissa; | ||
uint totalBorrows; | ||
uint totalReserves; | ||
uint totalSupply; | ||
uint totalCash; | ||
bool isListed; | ||
uint collateralFactorMantissa; | ||
address underlyingAssetAddress; | ||
uint cTokenDecimals; | ||
uint underlyingDecimals; | ||
} | ||
|
||
function cTokenMetadata(CToken cToken) public returns (CTokenMetadata memory) { | ||
uint exchangeRateCurrent = cToken.exchangeRateCurrent(); | ||
Comptroller comptroller = Comptroller(address(cToken.comptroller())); | ||
(bool isListed, uint collateralFactorMantissa) = comptroller.markets(address(cToken)); | ||
address underlyingAssetAddress; | ||
uint underlyingDecimals; | ||
|
||
if (compareStrings(cToken.symbol(), "cETH")) { | ||
underlyingAssetAddress = address(0); | ||
underlyingDecimals = 18; | ||
} else { | ||
CErc20 cErc20 = CErc20(address(cToken)); | ||
underlyingAssetAddress = cErc20.underlying(); | ||
underlyingDecimals = EIP20Interface(cErc20.underlying()).decimals(); | ||
} | ||
|
||
return CTokenMetadata({ | ||
cToken: address(cToken), | ||
exchangeRateCurrent: exchangeRateCurrent, | ||
supplyRatePerBlock: cToken.supplyRatePerBlock(), | ||
borrowRatePerBlock: cToken.borrowRatePerBlock(), | ||
reserveFactorMantissa: cToken.reserveFactorMantissa(), | ||
totalBorrows: cToken.totalBorrows(), | ||
totalReserves: cToken.totalReserves(), | ||
totalSupply: cToken.totalSupply(), | ||
totalCash: cToken.getCash(), | ||
isListed: isListed, | ||
collateralFactorMantissa: collateralFactorMantissa, | ||
underlyingAssetAddress: underlyingAssetAddress, | ||
cTokenDecimals: cToken.decimals(), | ||
underlyingDecimals: underlyingDecimals | ||
}); | ||
} | ||
|
||
function cTokenMetadataAll(CToken[] calldata cTokens) external returns (CTokenMetadata[] memory) { | ||
uint cTokenCount = cTokens.length; | ||
CTokenMetadata[] memory res = new CTokenMetadata[](cTokenCount); | ||
for (uint i = 0; i < cTokenCount; i++) { | ||
res[i] = cTokenMetadata(cTokens[i]); | ||
} | ||
return res; | ||
} | ||
|
||
struct CTokenBalances { | ||
address cToken; | ||
uint balanceOf; | ||
uint borrowBalanceCurrent; | ||
uint balanceOfUnderlying; | ||
uint tokenBalance; | ||
uint tokenAllowance; | ||
} | ||
|
||
function cTokenBalances(CToken cToken, address payable account) public returns (CTokenBalances memory) { | ||
uint balanceOf = cToken.balanceOf(account); | ||
uint borrowBalanceCurrent = cToken.borrowBalanceCurrent(account); | ||
uint balanceOfUnderlying = cToken.balanceOfUnderlying(account); | ||
uint tokenBalance; | ||
uint tokenAllowance; | ||
|
||
if (compareStrings(cToken.symbol(), "cETH")) { | ||
tokenBalance = account.balance; | ||
tokenAllowance = account.balance; | ||
} else { | ||
CErc20 cErc20 = CErc20(address(cToken)); | ||
EIP20Interface underlying = EIP20Interface(cErc20.underlying()); | ||
tokenBalance = underlying.balanceOf(account); | ||
tokenAllowance = underlying.allowance(account, address(cToken)); | ||
} | ||
|
||
return CTokenBalances({ | ||
cToken: address(cToken), | ||
balanceOf: balanceOf, | ||
borrowBalanceCurrent: borrowBalanceCurrent, | ||
balanceOfUnderlying: balanceOfUnderlying, | ||
tokenBalance: tokenBalance, | ||
tokenAllowance: tokenAllowance | ||
}); | ||
} | ||
|
||
function cTokenBalancesAll(CToken[] calldata cTokens, address payable account) external returns (CTokenBalances[] memory) { | ||
uint cTokenCount = cTokens.length; | ||
CTokenBalances[] memory res = new CTokenBalances[](cTokenCount); | ||
for (uint i = 0; i < cTokenCount; i++) { | ||
res[i] = cTokenBalances(cTokens[i], account); | ||
} | ||
return res; | ||
} | ||
|
||
struct CTokenUnderlyingPrice { | ||
address cToken; | ||
uint underlyingPrice; | ||
} | ||
|
||
function cTokenUnderlyingPrice(CToken cToken) public returns (CTokenUnderlyingPrice memory) { | ||
Comptroller comptroller = Comptroller(address(cToken.comptroller())); | ||
PriceOracle priceOracle = comptroller.oracle(); | ||
|
||
return CTokenUnderlyingPrice({ | ||
cToken: address(cToken), | ||
underlyingPrice: priceOracle.getUnderlyingPrice(cToken) | ||
}); | ||
} | ||
|
||
function cTokenUnderlyingPriceAll(CToken[] calldata cTokens) external returns (CTokenUnderlyingPrice[] memory) { | ||
uint cTokenCount = cTokens.length; | ||
CTokenUnderlyingPrice[] memory res = new CTokenUnderlyingPrice[](cTokenCount); | ||
for (uint i = 0; i < cTokenCount; i++) { | ||
res[i] = cTokenUnderlyingPrice(cTokens[i]); | ||
} | ||
return res; | ||
} | ||
|
||
struct AccountLimits { | ||
CToken[] markets; | ||
uint liquidity; | ||
uint shortfall; | ||
} | ||
|
||
function getAccountLimits(Comptroller comptroller, address account) public returns (AccountLimits memory) { | ||
(uint errorCode, uint liquidity, uint shortfall) = comptroller.getAccountLiquidity(account); | ||
require(errorCode == 0); | ||
|
||
return AccountLimits({ | ||
markets: comptroller.getAssetsIn(account), | ||
liquidity: liquidity, | ||
shortfall: shortfall | ||
}); | ||
} | ||
|
||
function compareStrings(string memory a, string memory b) internal pure returns (bool) { | ||
return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters