Skip to content

Instantly share code, notes, and snippets.

@zobront
Created December 14, 2023 21:07
Show Gist options
  • Save zobront/44a1909a8451d7649443d0e2717a96ab to your computer and use it in GitHub Desktop.
Save zobront/44a1909a8451d7649443d0e2717a96ab to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Test, console2 } from "forge-std/Test.sol";
import { Comptroller } from "../contracts/Comptroller.sol";
import { InterestRateModel } from "../contracts/InterestRateModel.sol";
import { CToken } from "../contracts/CToken.sol";
import { CErc20 } from "../contracts/CErc20.sol";
import { CErc721 } from "../contracts/CErc721.sol";
import { PriceOracle } from "../contracts/PriceOracle.sol";
import { JumpRateModelV2 } from "../contracts/JumpRateModelV2.sol";
import { CErc721InterestRateModel } from "../contracts/CErc721InterestRateModel.sol";
import "../contracts/CTokenInterfaces.sol";
import { AggregatorV3Interface } from "@chainlink/interfaces/AggregatorV3Interface.sol";
import { ChainlinkPriceOracle } from "../contracts/ChainlinkPriceOracle.sol";
import { FloorPriceFeedAdapter } from "../contracts/FloorPriceFeedAdapter.sol";
import { CEther, IWeth } from "../contracts/CEther.sol";
import { CEtherDelegator } from "../contracts/CEtherDelegator.sol";
import { CEtherDelegate } from "../contracts/CEtherDelegate.sol";
import { CErc721Delegate } from "../contracts/CERC721Delegate.sol";
import { CErc721Delegator } from "../contracts/CERC721Delegator.sol";
import { CErc721NoProxy } from "../contracts/CERC721NoProxy.sol";
import { CErc20InterestMarket } from "../contracts/CErc20InterestMarket.sol";
import { CErc20InterestMarketDelegator } from "../contracts/CErc20InterestMarketDelegator.sol";
import { CErc20InterestMarketDelegate } from "../contracts/CErc20InterestMarketDelegate.sol";
import { CErc20InterestMarketNoProxy } from "../contracts/CErc20InterestMarketNoProxy.sol";
import { CErc20Immutable } from "../contracts/CErc20Immutable.sol";
interface IERC721 {
function transferFrom(address from, address to, uint256 tokenId) external;
function balanceOf(address owner) external view returns (uint256 balance);
function approve(address to, uint256 tokenId) external;
function ownerOf(uint256 tokenId) external view returns (address owner);
}
interface IERC20 {
function transfer(address recipient, uint256 amount) external returns (bool);
function balanceOf(address owner) external view returns (uint256 balance);
function approve(address spender, uint256 amount) external returns (bool);
}
contract MockOracle {
uint price;
constructor(uint _price) {
price = _price;
}
function setPrice(uint _price) public {
price = _price;
}
function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80) {
return (0, int(price), 0, block.timestamp, 0);
}
}
contract BaseTest is Test {
Comptroller comptroller;
JumpRateModelV2 jumpRateModel;
CErc721InterestRateModel cErc721InterestRateModel;
address lender = makeAddr("lender");
address borrower = makeAddr("borrower");
address liquidator = makeAddr("liquidator");
address attacker = makeAddr("attacker");
address constant BAYC = 0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D;
address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
IWeth constant WETH = IWeth(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
AggregatorV3Interface constant ETHUSD = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
address constant USDUSDC = 0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6;
address constant BAYCETH = 0x352f2Bc3039429fC2fe62004a1575aE74001CfcE;
uint constant blocksPerYear = 2628000;
ChainlinkPriceOracle oracle;
CErc721 baycCERC721;
CErc20 erc20Market;
CErc20InterestMarket imMarket;
CEther cether;
function setUp() virtual public {
vm.createSelectFork("https://mainnet.infura.io/v3/fb419f740b7e401bad5bec77d0d285a5", 18764789); // ~1pm monday
//////////////////////////////////
////////// COMPTROLLER ///////////
//////////////////////////////////
comptroller = new Comptroller();
comptroller.initialize();
//////////////////////////////////
////// INTEREST RATE MODELS //////
//////////////////////////////////
jumpRateModel = new JumpRateModelV2(0, 0.04e18, 1.09e18, 0.8e18, address(this));
cErc721InterestRateModel = new CErc721InterestRateModel(2628000, 0.02e18, 0.1e18);
//////////////////////////////////
//////////// MARKETS /////////////
//////////////////////////////////
address baycCERC721Impl = address(new CErc721Delegate());
baycCERC721 = CErc721(address(new CErc721Delegator(
BAYC,
ComptrollerInterface(address(comptroller)),
InterestRateModel(address(cErc721InterestRateModel)),
2e26,
"BAYC Market",
"cBAYC",
8,
payable(address(this)),
baycCERC721Impl,
""
)));
baycCERC721._setReserveFactor(7.5e16);
imMarket = CErc20InterestMarket(address(new CErc20InterestMarketNoProxy(
USDC,
ComptrollerInterface(address(comptroller)),
InterestRateModel(address(jumpRateModel)),
2e14,
"cUSDC Interest Market",
"imcUSDC",
8,
payable(address(this))
)));
imMarket._setReserveFactor(7.5e16);
imMarket._setProtocolSeizeShare(2.8e16);
erc20Market = CErc20(address(new CErc20Immutable(
USDC,
ComptrollerInterface(address(comptroller)),
InterestRateModel(address(jumpRateModel)),
2e14,
"Fungify cUSDC",
"fcUSDC",
8,
payable(address(this))
)));
erc20Market._setReserveFactor(7.5e16);
erc20Market._setProtocolSeizeShare(2.8e16);
cether = CEther(payable(address(new CEtherDelegator(
ComptrollerInterface(address(comptroller)),
InterestRateModel(address(jumpRateModel)),
2e14,
"Fungify cETH",
"fcETH",
8,
payable(address(this)),
address(new CEtherDelegate(WETH)),
""
))));
cether._setReserveFactor(7.5e16);
cether._setProtocolSeizeShare(2.8e16);
//////////////////////////////////
//////////// ORACLES /////////////
//////////////////////////////////
oracle = new ChainlinkPriceOracle();
address baycAdapter = address(new FloorPriceFeedAdapter(
AggregatorV3Interface(BAYCETH),
ETHUSD
));
oracle.setAssetPriceFeed(CToken(address(baycCERC721)), baycAdapter);
oracle.setAssetPriceFeed(CToken(address(imMarket)), USDUSDC);
oracle.setAssetPriceFeed(CToken(address(erc20Market)), USDUSDC);
oracle.setAssetPriceFeed(CToken(address(cether)), address(ETHUSD));
//////////////////////////////////
////// COMPTROLLER SETTINGS //////
//////////////////////////////////
comptroller._setPriceOracle(PriceOracle(address(oracle)));
comptroller._setLiquidationIncentive(1.08e18);
comptroller._supportMarket(CToken(address(baycCERC721)));
comptroller._setCollateralFactor(CToken(address(baycCERC721)), 0.85e18);
comptroller._supportMarket(CToken(address(erc20Market)));
comptroller._setCollateralFactor(CToken(address(erc20Market)), 0.85e18);
comptroller._supportMarket(CToken(address(cether)));
comptroller._setCollateralFactor(CToken(address(cether)), 0.85e18);
comptroller._supportMarket(CToken(address(imMarket)));
comptroller._setCollateralFactor(CToken(address(imMarket)), 0.85e18);
comptroller._updateInterestMarket(address(imMarket));
comptroller._setAdminWhitelist(liquidator, true);
comptroller._setAdminWhitelist(attacker, true);
//////////////////////////////////
////////// TOKEN SETUP ///////////
//////////////////////////////////
address USDC_WHALE = 0x28C6c06298d514Db089934071355E5743bf21d60;
vm.prank(USDC_WHALE);
IERC20(USDC).transfer(address(this), 100_000_000e6);
}
function _distributeERC20(address token, address to, uint amount, address marketToApprove) internal {
IERC20(token).transfer(to, amount);
vm.prank(to);
IERC20(token).approve(marketToApprove, amount);
}
function _distributeERC721(address token, address to, uint tokenId, address marketToApprove) internal {
address from = IERC721(token).ownerOf(tokenId);
vm.prank(from);
IERC721(token).transferFrom(from, to, tokenId);
vm.prank(to);
IERC721(token).approve(marketToApprove, tokenId);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment