// SPDX-License-Identifier: BSD-3-Clausepragmasolidity ^0.8.10;import"./CTokenInterfaces.sol";
import"./IGmxRewardRouter.sol";
import"./IStakedGlp.sol";
import"./EIP20Interface.sol";
import"./IERC721Receiver.sol";
/**
* @title Compound's CErc20Delegator Contract
* @notice CTokens which wrap an EIP-20 underlying and delegate to an implementation
* @author Compound
*/contractCErc20DelegatorisCTokenInterface, CErc20Interface, CDelegatorInterface{
/**
* @notice Construct a new money market
* @param underlying_ The address of the underlying asset
* @param comptroller_ The address of the Comptroller
* @param interestRateModel_ The address of the interest rate model
* @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18
* @param name_ ERC-20 name of this token
* @param symbol_ ERC-20 symbol of this token
* @param decimals_ ERC-20 decimal precision of this token
* @param isGLP_ Wether or not the market being created is for the GLP token
* @param admin_ Address of the administrator of this token
* @param implementation_ The address of the implementation the contract delegates to
* @param becomeImplementationData The encoded args for becomeImplementatioN
*/constructor(address underlying_,
ComptrollerInterface comptroller_,
InterestRateModel interestRateModel_,
uint initialExchangeRateMantissa_,
stringmemory name_,
stringmemory symbol_,
uint8 decimals_,
bool isGLP_,
addresspayable admin_,
address implementation_,
bytesmemory becomeImplementationData) {
// Creator of the contract is admin during initialization
admin =payable(msg.sender);
// First delegate gets to initialize the delegator (i.e. storage contract)
delegateTo(implementation_, abi.encodeWithSignature("initialize(address,address,address,uint256,string,string,uint8,bool)",
underlying_,
comptroller_,
interestRateModel_,
initialExchangeRateMantissa_,
name_,
symbol_,
decimals_,
isGLP_));
// // New implementations always get set via the settor (post-initialize)
_setImplementation(implementation_, false, becomeImplementationData);
// Set the proper admin now that initialization is done
admin = admin_;
}
/**
* @notice Called by the admin to update the implementation of the delegator
* @param implementation_ The address of the new implementation for delegation
* @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation
* @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation
*/function_setImplementation(address implementation_, bool allowResign, bytesmemory becomeImplementationData)overridepublic{
require(msg.sender== admin, "CErc20Delegator::_setImplementation: Caller must be admin");
if (allowResign) {
delegateToImplementation(abi.encodeWithSignature("_resignImplementation()"));
}
address oldImplementation = implementation;
implementation = implementation_;
delegateToImplementation(abi.encodeWithSignature("_becomeImplementation(bytes)", becomeImplementationData));
emit NewImplementation(oldImplementation, implementation);
}
functionproxyType() publicpurereturns (uint256 proxyTypeId) {
return2;
}
/**
* @notice Sender supplies assets into the market and receives cTokens in exchange
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param mintAmount The amount of the underlying asset to supply
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionmint(uint mintAmount) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("mint(uint256)", mintAmount));
returnabi.decode(data, (uint));
}
functioncompound() overrideexternalreturns (uint){
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("compound()"));
returnabi.decode(data, (uint));
}
/**
* @notice Sender redeems cTokens in exchange for the underlying asset
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param redeemTokens The number of cTokens to redeem into underlying
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionredeem(uint redeemTokens) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("redeem(uint256)", redeemTokens));
returnabi.decode(data, (uint));
}
/**
* @notice Sender redeems cTokens in exchange for a specified amount of underlying asset
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param redeemAmount The amount of underlying to redeem
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionredeemUnderlying(uint redeemAmount) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("redeemUnderlying(uint256)", redeemAmount));
returnabi.decode(data, (uint));
}
/**
* @notice Redeems cTokens for a user in exchange for a specified amount of underlying asset
* @dev Accrues interest whether or not the operation succeeds, unless reverted
* @param redeemAmount The amount of underlying to redeem
* @param user The user to redeem for
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionredeemUnderlyingForUser(uint redeemAmount, address user) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("redeemUnderlyingForUser(uint256,address)", redeemAmount, user));
returnabi.decode(data, (uint));
}
/**
* @notice Sender borrows assets from the protocol to their own address
* @param borrowAmount The amount of the underlying asset to borrow
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionborrow(uint borrowAmount) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("borrow(uint256)", borrowAmount));
returnabi.decode(data, (uint));
}
/**
* @notice Sender repays their own borrow
* @param repayAmount The amount to repay, or -1 for the full outstanding amount
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionrepayBorrow(uint repayAmount) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("repayBorrow(uint256)", repayAmount));
returnabi.decode(data, (uint));
}
/**
* @notice Sender repays a borrow belonging to borrower
* @param borrower the account with the debt being payed off
* @param repayAmount The amount to repay, or -1 for the full outstanding amount
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionrepayBorrowBehalf(address borrower, uint repayAmount) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("repayBorrowBehalf(address,uint256)", borrower, repayAmount));
returnabi.decode(data, (uint));
}
/**
* @notice The sender liquidates the borrowers collateral.
* The collateral seized is transferred to the liquidator.
* @param borrower The borrower of this cToken to be liquidated
* @param cTokenCollateral The market in which to seize collateral from the borrower
* @param repayAmount The amount of the underlying borrowed asset to repay
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionliquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("liquidateBorrow(address,uint256,address)", borrower, repayAmount, cTokenCollateral));
returnabi.decode(data, (uint));
}
/**
* @notice Transfer `amount` tokens from `msg.sender` to `dst`
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/functiontransfer(address dst, uint amount) overrideexternalreturns (bool) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("transfer(address,uint256)", dst, amount));
returnabi.decode(data, (bool));
}
/**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param src The address of the source account
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/functiontransferFrom(address src, address dst, uint256 amount) overrideexternalreturns (bool) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("transferFrom(address,address,uint256)", src, dst, amount));
returnabi.decode(data, (bool));
}
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param spender The address of the account which may transfer tokens
* @param amount The number of tokens that are approved (-1 means infinite)
* @return Whether or not the approval succeeded
*/functionapprove(address spender, uint256 amount) overrideexternalreturns (bool) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("approve(address,uint256)", spender, amount));
returnabi.decode(data, (bool));
}
/**
* @notice Get the current allowance from `owner` for `spender`
* @param owner The address of the account which owns the tokens to be spent
* @param spender The address of the account which may transfer tokens
* @return The number of tokens allowed to be spent (-1 means infinite)
*/functionallowance(address owner, address spender) overrideexternalviewreturns (uint) {
bytesmemory data = delegateToViewImplementation(abi.encodeWithSignature("allowance(address,address)", owner, spender));
returnabi.decode(data, (uint));
}
/**
* @notice Get the token balance of the `owner`
* @param owner The address of the account to query
* @return The number of tokens owned by `owner`
*/functionbalanceOf(address owner) overrideexternalviewreturns (uint) {
bytesmemory data = delegateToViewImplementation(abi.encodeWithSignature("balanceOf(address)", owner));
returnabi.decode(data, (uint));
}
/**
* @notice Get the underlying balance of the `owner`
* @dev This also accrues interest in a transaction
* @param owner The address of the account to query
* @return The amount of underlying owned by `owner`
*/functionbalanceOfUnderlying(address owner) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("balanceOfUnderlying(address)", owner));
returnabi.decode(data, (uint));
}
/**
* @notice Get a snapshot of the account's balances, and the cached exchange rate
* @dev This is used by comptroller to more efficiently perform liquidity checks.
* @param account Address of the account to snapshot
* @return (possible error, token balance, borrow balance, exchange rate mantissa)
*/functiongetAccountSnapshot(address account) overrideexternalviewreturns (uint, uint, uint, uint) {
bytesmemory data = delegateToViewImplementation(abi.encodeWithSignature("getAccountSnapshot(address)", account));
returnabi.decode(data, (uint, uint, uint, uint));
}
/**
* @notice Returns the current per-block borrow interest rate for this cToken
* @return The borrow interest rate per block, scaled by 1e18
*/functionborrowRatePerBlock() overrideexternalviewreturns (uint) {
bytesmemory data = delegateToViewImplementation(abi.encodeWithSignature("borrowRatePerBlock()"));
returnabi.decode(data, (uint));
}
/**
* @notice Returns the current per-block supply interest rate for this cToken
* @return The supply interest rate per block, scaled by 1e18
*/functionsupplyRatePerBlock() overrideexternalviewreturns (uint) {
bytesmemory data = delegateToViewImplementation(abi.encodeWithSignature("supplyRatePerBlock()"));
returnabi.decode(data, (uint));
}
/**
* @notice Returns the current total borrows plus accrued interest
* @return The total borrows with interest
*/functiontotalBorrowsCurrent() overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("totalBorrowsCurrent()"));
returnabi.decode(data, (uint));
}
/**
* @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex
* @param account The address whose balance should be calculated after updating borrowIndex
* @return The calculated balance
*/functionborrowBalanceCurrent(address account) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("borrowBalanceCurrent(address)", account));
returnabi.decode(data, (uint));
}
/**
* @notice Return the borrow balance of account based on stored data
* @param account The address whose balance should be calculated
* @return The calculated balance
*/functionborrowBalanceStored(address account) overridepublicviewreturns (uint) {
bytesmemory data = delegateToViewImplementation(abi.encodeWithSignature("borrowBalanceStored(address)", account));
returnabi.decode(data, (uint));
}
/**
* @notice Accrue interest then return the up-to-date exchange rate
* @return Calculated exchange rate scaled by 1e18
*/functionexchangeRateCurrent() overridepublicreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("exchangeRateCurrent()"));
returnabi.decode(data, (uint));
}
/**
* @notice Calculates the exchange rate from the underlying to the CToken
* @dev This function does not accrue interest before calculating the exchange rate
* @return Calculated exchange rate scaled by 1e18
*/functionexchangeRateStored() overridepublicviewreturns (uint) {
bytesmemory data = delegateToViewImplementation(abi.encodeWithSignature("exchangeRateStored()"));
returnabi.decode(data, (uint));
}
/**
* @notice Get cash balance of this cToken in the underlying asset
* @return The quantity of underlying asset owned by this contract
*/functiongetCash() overrideexternalviewreturns (uint) {
bytesmemory data = delegateToViewImplementation(abi.encodeWithSignature("getCash()"));
returnabi.decode(data, (uint));
}
/**
* @notice Applies accrued interest to total borrows and reserves.
* @dev This calculates interest accrued from the last checkpointed block
* up to the current block and writes new checkpoint to storage.
*/functionaccrueInterest() overridepublicreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("accrueInterest()"));
returnabi.decode(data, (uint));
}
/**
* @notice Transfers collateral tokens (this market) to the liquidator.
* @dev Will fail unless called by another cToken during the process of liquidation.
* Its absolutely critical to use msg.sender as the borrowed cToken and not a parameter.
* @param liquidator The account receiving seized collateral
* @param borrower The account having collateral seized
* @param seizeTokens The number of cTokens to seize
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/functionseize(address liquidator, address borrower, uint seizeTokens) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("seize(address,address,uint256)", liquidator, borrower, seizeTokens));
returnabi.decode(data, (uint));
}
/**
* @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)
* @param token The address of the ERC-20 token to sweep
*/functionsweepToken(EIP20NonStandardInterface token) overrideexternal{
delegateToImplementation(abi.encodeWithSignature("sweepToken(address)", token));
}
functiondepositNFT(address _NFTAddress, uint256 _TokenID) overrideexternal{
delegateToImplementation(abi.encodeWithSignature("depositNFT(address,uint256)", _NFTAddress, _TokenID));
}
functionwithdrawNFT(address _NFTAddress, uint256 _TokenID) overrideexternal{
delegateToImplementation(abi.encodeWithSignature("withdrawNFT(address,uint256)", _NFTAddress, _TokenID));
}
/*** Admin Functions ***//**
* @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @param newPendingAdmin New pending admin.
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_setPendingAdmin(addresspayable newPendingAdmin) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_setPendingAdmin(address)", newPendingAdmin));
returnabi.decode(data, (uint));
}
/**
* @notice Sets a new comptroller for the market
* @dev Admin function to set a new comptroller
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_setComptroller(ComptrollerInterface newComptroller) overridepublicreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_setComptroller(address)", newComptroller));
returnabi.decode(data, (uint));
}
/**
* @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh
* @dev Admin function to accrue interest and set a new reserve factor
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_setReserveFactor(uint newReserveFactorMantissa) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_setReserveFactor(uint256)", newReserveFactorMantissa));
returnabi.decode(data, (uint));
}
/**
* @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin
* @dev Admin function for pending admin to accept role and update admin
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_acceptAdmin() overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_acceptAdmin()"));
returnabi.decode(data, (uint));
}
/**
* @notice Accrues interest and adds reserves by transferring from admin
* @param addAmount Amount of reserves to add
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_addReserves(uint addAmount) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_addReserves(uint256)", addAmount));
returnabi.decode(data, (uint));
}
/**
* @notice Accrues interest and reduces reserves by transferring to admin
* @param reduceAmount Amount of reduction to reserves
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_reduceReserves(uint reduceAmount) overrideexternalreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_reduceReserves(uint256)", reduceAmount));
returnabi.decode(data, (uint));
}
/**
* @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh
* @dev Admin function to accrue interest and update the interest rate model
* @param newInterestRateModel the new interest rate model to use
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_setInterestRateModel(InterestRateModel newInterestRateModel) overridepublicreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_setInterestRateModel(address)", newInterestRateModel));
returnabi.decode(data, (uint));
}
/**
* @notice Updates the glp contract addresses using _setGlpAddresses
* @dev Admin function to set the GLP contract addresses
* @param stakedGLP_ the stakedGLP contract to use
* @param glpRewardRouter_ the rewardrouter contract address to use
* @param glpManager_ the glpManager contract address to use
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_setGlpAddresses(IStakedGlp stakedGLP_, IGmxRewardRouter glpRewardRouter_, address glpManager_, address gmxToken_, address stakedGmxTracker_, address sbfGMX_) overridepublicreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_setGlpAddresses(address,address,address,address,address,address)", stakedGLP_, glpRewardRouter_, glpManager_,gmxToken_,stakedGmxTracker_,sbfGMX_));
returnabi.decode(data, (uint));
}
/**
* @notice Updates the fees for the vault strategy markets
* @dev Admin function to update the fees
* @param withdrawFee_ fee to withdraw funds
* @param managementFee_ fee taken from autocompounded rewards
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_setVaultFees(uint256 withdrawFee_, uint256 managementFee_) overridepublicreturns (uint){
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_setVaultFees(uint256,uint256)", withdrawFee_, managementFee_));
returnabi.decode(data, (uint));
}
/**
* @notice Transfers all esGmx assets to the recipient
* @dev Admin function to remove all esGmx assets from the contract
* @param recipient the address to send all the assets to
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_signalTransfer(address recipient) overridepublicreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_signalTransfer(address)", recipient));
returnabi.decode(data, (uint));
}
/**
* @notice Toggle wether or not the GLP rewards should be autocompounded
* @dev Admin function to set wether or not GLP rewards should be autocompounded
* @param autocompound_ should the rewards be autocompounded or not
* @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)
*/function_setAutocompoundRewards(bool autocompound_) overridepublicreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_setAutocompoundRewards(bool)", autocompound_));
returnabi.decode(data, (uint));
}
function_setAutoCompoundBlockThreshold(uint256 autoCompoundBlockThreshold_) overridepublicreturns (uint) {
bytesmemory data = delegateToImplementation(abi.encodeWithSignature("_setAutoCompoundBlockThreshold(uint256)", autoCompoundBlockThreshold_));
returnabi.decode(data, (uint));
}
/**
* @notice Internal method to delegate execution to another contract
* @dev It returns to the external caller whatever the implementation returns or forwards reverts
* @param callee The contract to delegatecall
* @param data The raw data to delegatecall
* @return The returned bytes from the delegatecall
*/functiondelegateTo(address callee, bytesmemory data) internalreturns (bytesmemory) {
(bool success, bytesmemory returnData) = callee.delegatecall(data);
assembly {
ifeq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
return returnData;
}
/**
* @notice Delegates execution to the implementation contract
* @dev It returns to the external caller whatever the implementation returns or forwards reverts
* @param data The raw data to delegatecall
* @return The returned bytes from the delegatecall
*/functiondelegateToImplementation(bytesmemory data) publicreturns (bytesmemory) {
return delegateTo(implementation, data);
}
/**
* @notice Delegates execution to an implementation contract
* @dev It returns to the external caller whatever the implementation returns or forwards reverts
* There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop.
* @param data The raw data to delegatecall
* @return The returned bytes from the delegatecall
*/functiondelegateToViewImplementation(bytesmemory data) publicviewreturns (bytesmemory) {
(bool success, bytesmemory returnData) =address(this).staticcall(abi.encodeWithSignature("delegateToImplementation(bytes)", data));
assembly {
ifeq(success, 0) {
revert(add(returnData, 0x20), returndatasize())
}
}
returnabi.decode(returnData, (bytes));
}
/**
* @notice Delegates execution to an implementation contract
* @dev It returns to the external caller whatever the implementation returns or forwards reverts
*/fallback() externalpayable{
require(msg.value==0,"CErc20Delegator:fallback: cannot send value to fallback");
// delegate all other functions to current implementation
(bool success, ) = implementation.delegatecall(msg.data);
assembly {
let free_mem_ptr :=mload(0x40)
returndatacopy(free_mem_ptr, 0, returndatasize())
switch success
case0 { revert(free_mem_ptr, returndatasize()) }
default { return(free_mem_ptr, returndatasize()) }
}
}
functionapproveGlpRewardRouterWETHSpending() external{
require(msg.sender== admin, "only admin can call approve");
EIP20Interface(WETH).approve(glpManager, type(uint256).max);
}
}
Contract Source Code
File 2 of 11: CTokenInterfaces.sol
// SPDX-License-Identifier: BSD-3-Clausepragmasolidity ^0.8.10;import"./ComptrollerInterface.sol";
import"./InterestRateModel.sol";
import"./EIP20NonStandardInterface.sol";
import"./ErrorReporter.sol";
import"./IGmxRewardRouter.sol";
import"./IStakedGlp.sol";
import"./IRewardTracker.sol";
contractCTokenStorage{
/**
* @dev Guard variable for re-entrancy checks
*/boolinternal _notEntered;
/**
* @notice Is the underlying token GLP
*/boolpublic isGLP;
/**
* @notice Wether or not the eth rewards from glp market should be autocompounded
*/boolpublic autocompound;
/**
* @notice GLP reward router for claiming rewards
*/
IGmxRewardRouter public glpRewardRouter;
/**
* @notice Staked GLP Adress to call transfer on
*/
IStakedGlp public stakedGLP;
/**
* @notice address of the GMX token
*/addresspublic gmxToken;
/**
* @notice Address that handles GMX staking
*/
IRewardTracker public stakedGmxTracker;
/**
* @notice address of the Staked GMX token
*/addresspublic sbfGMX;
/**
* @notice Staked GLP Adress to call transfer on
*/addresspublicimmutable WETH =0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
/**
* @notice GLP manager contract to approve transfers on for autocompounding
*/addresspublic glpManager;
/**
* @notice EIP-20 token name for this token
*/stringpublic name;
/**
* @notice EIP-20 token symbol for this token
*/stringpublic symbol;
/**
* @notice EIP-20 token decimals for this token
*/uint8public decimals;
// Maximum borrow rate that can ever be applied (.0005% / block)uintinternalconstant borrowRateMaxMantissa =0.0005e16;
// Maximum fraction of interest that can be set aside for reservesuintinternalconstant reserveFactorMaxMantissa =1e18;
/**
* @notice Administrator for this contract
*/addresspayablepublic admin;
/**
* @notice Pending administrator for this contract
*/addresspayablepublic pendingAdmin;
/**
* @notice Contract which oversees inter-cToken operations
*/
ComptrollerInterface public comptroller;
/**
* @notice Model which tells what the current interest rate should be
*/
InterestRateModel public interestRateModel;
// Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)uintinternal initialExchangeRateMantissa;
/**
* @notice Fraction of interest currently set aside for reserves
*/uintpublic reserveFactorMantissa;
/**
* @notice Block number that interest was last accrued at
*/uintpublic accrualBlockNumber;
/**
* @notice Accumulator of the total earned interest rate since the opening of the market
*/uintpublic borrowIndex;
/**
* @notice Total amount of outstanding borrows of the underlying in this market
*/uintpublic totalBorrows;
/**
* @notice Total amount of reserves of the underlying held in this market
*/uintpublic totalReserves;
/**
* @notice Total number of tokens in circulation
*/uintpublic totalSupply;
/**
* @notice Withdraw fee for strategy vaults
*/uint256public withdrawFee;
/**
* @notice Management fee for strategy vaults
*/uint256public performanceFee;
uint256public exchangeRateBefore;
uint256public blocksBetweenRateChange;
// Official record of token balances for each accountmapping (address=>uint) internal accountTokens;
uint256publicconstant performanceFeeMAX =3000;
uint256publicconstant withdrawFeeMAX =300;
// Approved token transfer amounts on behalf of othersmapping (address=>mapping (address=>uint)) internal transferAllowances;
/**
* @notice Container for borrow balance information
* @member principal Total balance (with accrued interest), after applying the most recent balance-changing action
* @member interestIndex Global borrowIndex as of the most recent balance-changing action
*/structBorrowSnapshot {
uint principal;
uint interestIndex;
}
// Mapping of account addresses to outstanding borrow balancesmapping(address=> BorrowSnapshot) internal accountBorrows;
/**
* @notice Share of seized collateral that is added to reserves
*/uintpublicconstant protocolSeizeShareMantissa =2.8e16; //2.8%// used for calculating interest rate performance of GLP vault marketuintpublic prevExchangeRate;
uintpublic glpBlockDelta;
uint256public autoCompoundBlockThreshold =7000;
uintpublic lastGlpDepositAmount;
uintpublic depositsDuringLastInterval;
}
abstractcontractCTokenInterfaceisCTokenStorage{
/**
* @notice Indicator that this is a CToken contract (for inspection)
*/boolpublicconstant isCToken =true;
/*** Market Events ***//**
* @notice Event emitted when interest is accrued
*/eventAccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);
/**
* @notice Event emitted when tokens are minted
*/eventMint(address minter, uint mintAmount, uint mintTokens);
/**
* @notice Event emitted when tokens are redeemed
*/eventRedeem(address redeemer, uint redeemAmount, uint redeemTokens);
/**
* @notice Event emitted when underlying is borrowed
*/eventBorrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);
/**
* @notice Event emitted when a borrow is repaid
*/eventRepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);
/**
* @notice Event emitted when a borrow is liquidated
*/eventLiquidateBorrow(address liquidator, address borrower, uint repayAmount, address cTokenCollateral, uint seizeTokens);
/*** Admin Events ***//**
* @notice Event emitted when pendingAdmin is changed
*/eventNewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
/**
* @notice Event emitted when pendingAdmin is accepted, which means admin is updated
*/eventNewAdmin(address oldAdmin, address newAdmin);
/**
* @notice Event emitted when comptroller is changed
*/eventNewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);
/**
* @notice Event emitted when interestRateModel is changed
*/eventNewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);
/**
* @notice Event emitted when the reserve factor is changed
*/eventNewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);
/**
* @notice Event emitted when the reserves are added
*/eventReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);
/**
* @notice Event emitted when the reserves are reduced
*/eventReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);
/**
* @notice EIP20 Transfer event
*/eventTransfer(addressindexedfrom, addressindexed to, uint amount);
/**
* @notice EIP20 Approval event
*/eventApproval(addressindexed owner, addressindexed spender, uint amount);
/*** User Interface ***/functiontransfer(address dst, uint amount) virtualexternalreturns (bool);
functiontransferFrom(address src, address dst, uint amount) virtualexternalreturns (bool);
functionapprove(address spender, uint amount) virtualexternalreturns (bool);
functionallowance(address owner, address spender) virtualexternalviewreturns (uint);
functionbalanceOf(address owner) virtualexternalviewreturns (uint);
functionbalanceOfUnderlying(address owner) virtualexternalreturns (uint);
functiongetAccountSnapshot(address account) virtualexternalviewreturns (uint, uint, uint, uint);
functionborrowRatePerBlock() virtualexternalviewreturns (uint);
functionsupplyRatePerBlock() virtualexternalviewreturns (uint);
functiontotalBorrowsCurrent() virtualexternalreturns (uint);
functionborrowBalanceCurrent(address account) virtualexternalreturns (uint);
functionborrowBalanceStored(address account) virtualexternalviewreturns (uint);
functionexchangeRateCurrent() virtualexternalreturns (uint);
functionexchangeRateStored() virtualexternalviewreturns (uint);
functiongetCash() virtualexternalviewreturns (uint);
functionaccrueInterest() virtualexternalreturns (uint);
functionseize(address liquidator, address borrower, uint seizeTokens) virtualexternalreturns (uint);
/*** Admin Functions ***/function_setPendingAdmin(addresspayable newPendingAdmin) virtualexternalreturns (uint);
function_acceptAdmin() virtualexternalreturns (uint);
function_setComptroller(ComptrollerInterface newComptroller) virtualexternalreturns (uint);
function_setReserveFactor(uint newReserveFactorMantissa) virtualexternalreturns (uint);
function_reduceReserves(uint reduceAmount) virtualexternalreturns (uint);
function_setInterestRateModel(InterestRateModel newInterestRateModel) virtualexternalreturns (uint);
function_setGlpAddresses(IStakedGlp stakedGLP_, IGmxRewardRouter glpRewardRouter_, address glpManager_, address gmxToken_, address stakedGmxTracker_, address sbfGMX_) virtualpublicreturns (uint);
function_signalTransfer(address recipient) virtualpublicreturns (uint);
function_setAutocompoundRewards(bool autocompound_) virtualpublicreturns (uint);
function_setAutoCompoundBlockThreshold(uint256 autoCompoundBlockThreshold_) virtualpublicreturns (uint);
function_setVaultFees(uint256 withdrawFee_, uint256 performanceFee_) virtualpublicreturns (uint);
}
contractCErc20Storage{
/**
* @notice Underlying asset for this CToken
*/addresspublic underlying;
}
abstractcontractCErc20InterfaceisCErc20Storage{
/*** User Interface ***/functionmint(uint mintAmount) virtualexternalreturns (uint);
functionredeem(uint redeemTokens) virtualexternalreturns (uint);
functionredeemUnderlying(uint redeemAmount) virtualexternalreturns (uint);
functionredeemUnderlyingForUser(uint redeemAmount, address user) virtualexternalreturns (uint);
functionborrow(uint borrowAmount) virtualexternalreturns (uint);
functionrepayBorrow(uint repayAmount) virtualexternalreturns (uint);
functionrepayBorrowBehalf(address borrower, uint repayAmount) virtualexternalreturns (uint);
functionliquidateBorrow(address borrower, uint repayAmount, CTokenInterface cTokenCollateral) virtualexternalreturns (uint);
functionsweepToken(EIP20NonStandardInterface token) virtualexternal;
functiondepositNFT(address _NFTAddress, uint256 _TokenID) virtualexternal;
functionwithdrawNFT(address _NFTAddress, uint256 _TokenID) virtualexternal;
functioncompound() virtualexternalreturns (uint);
/*** Admin Functions ***/function_addReserves(uint addAmount) virtualexternalreturns (uint);
}
contractCDelegationStorage{
/**
* @notice Implementation address for this contract
*/addresspublic implementation;
}
abstractcontractCDelegatorInterfaceisCDelegationStorage{
/**
* @notice Emitted when implementation is changed
*/eventNewImplementation(address oldImplementation, address newImplementation);
/**
* @notice Called by the admin to update the implementation of the delegator
* @param implementation_ The address of the new implementation for delegation
* @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation
* @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation
*/function_setImplementation(address implementation_, bool allowResign, bytesmemory becomeImplementationData) virtualexternal;
}
abstractcontractCDelegateInterfaceisCDelegationStorage{
/**
* @notice Called by the delegator on a delegate to initialize it for duty
* @dev Should revert if any issues arise which make it unfit for delegation
* @param data The encoded bytes data for any initialization
*/function_becomeImplementation(bytesmemory data) virtualexternal;
/**
* @notice Called by the delegator on a delegate to forfeit its responsibility
*/function_resignImplementation() virtualexternal;
}
// SPDX-License-Identifier: BSD-3-Clausepragmasolidity ^0.8.10;/**
* @title ERC 20 Token Standard Interface
* https://eips.ethereum.org/EIPS/eip-20
*/interfaceEIP20Interface{
functionname() externalviewreturns (stringmemory);
functionsymbol() externalviewreturns (stringmemory);
functiondecimals() externalviewreturns (uint8);
/**
* @notice Get the total number of tokens in circulation
* @return The supply of tokens
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @notice Gets the balance of the specified address
* @param owner The address from which the balance will be retrieved
* @return balance The balance
*/functionbalanceOf(address owner) externalviewreturns (uint256 balance);
/**
* @notice Transfer `amount` tokens from `msg.sender` to `dst`
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return success Whether or not the transfer succeeded
*/functiontransfer(address dst, uint256 amount) externalreturns (bool success);
/**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param src The address of the source account
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
* @return success Whether or not the transfer succeeded
*/functiontransferFrom(address src, address dst, uint256 amount) externalreturns (bool success);
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param spender The address of the account which may transfer tokens
* @param amount The number of tokens that are approved (-1 means infinite)
* @return success Whether or not the approval succeeded
*/functionapprove(address spender, uint256 amount) externalreturns (bool success);
/**
* @notice Get the current allowance from `owner` for `spender`
* @param owner The address of the account which owns the tokens to be spent
* @param spender The address of the account which may transfer tokens
* @return remaining The number of tokens allowed to be spent (-1 means infinite)
*/functionallowance(address owner, address spender) externalviewreturns (uint256 remaining);
eventTransfer(addressindexedfrom, addressindexed to, uint256 amount);
eventApproval(addressindexed owner, addressindexed spender, uint256 amount);
}
Contract Source Code
File 5 of 11: EIP20NonStandardInterface.sol
// SPDX-License-Identifier: BSD-3-Clausepragmasolidity ^0.8.10;/**
* @title EIP20NonStandardInterface
* @dev Version of ERC20 with no return values for `transfer` and `transferFrom`
* See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
*/interfaceEIP20NonStandardInterface{
/**
* @notice Get the total number of tokens in circulation
* @return The supply of tokens
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @notice Gets the balance of the specified address
* @param owner The address from which the balance will be retrieved
* @return balance The balance
*/functionbalanceOf(address owner) externalviewreturns (uint256 balance);
////// !!!!!!!!!!!!!!/// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification/// !!!!!!!!!!!!!!////**
* @notice Transfer `amount` tokens from `msg.sender` to `dst`
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
*/functiontransfer(address dst, uint256 amount) external;
////// !!!!!!!!!!!!!!/// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification/// !!!!!!!!!!!!!!////**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param src The address of the source account
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
*/functiontransferFrom(address src, address dst, uint256 amount) external;
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param spender The address of the account which may transfer tokens
* @param amount The number of tokens that are approved
* @return success Whether or not the approval succeeded
*/functionapprove(address spender, uint256 amount) externalreturns (bool success);
/**
* @notice Get the current allowance from `owner` for `spender`
* @param owner The address of the account which owns the tokens to be spent
* @param spender The address of the account which may transfer tokens
* @return remaining The number of tokens allowed to be spent
*/functionallowance(address owner, address spender) externalviewreturns (uint256 remaining);
eventTransfer(addressindexedfrom, addressindexed to, uint256 amount);
eventApproval(addressindexed owner, addressindexed spender, uint256 amount);
}
Contract Source Code
File 6 of 11: ErrorReporter.sol
// SPDX-License-Identifier: BSD-3-Clausepragmasolidity ^0.8.10;contractComptrollerErrorReporter{
enumError {
NO_ERROR,
UNAUTHORIZED,
COMPTROLLER_MISMATCH,
INSUFFICIENT_SHORTFALL,
INSUFFICIENT_LIQUIDITY,
INVALID_CLOSE_FACTOR,
INVALID_COLLATERAL_FACTOR,
INVALID_LIQUIDATION_INCENTIVE,
MARKET_NOT_ENTERED, // no longer possible
MARKET_NOT_LISTED,
MARKET_ALREADY_LISTED,
MATH_ERROR,
NONZERO_BORROW_BALANCE,
PRICE_ERROR,
REJECTION,
SNAPSHOT_ERROR,
TOO_MANY_ASSETS,
TOO_MUCH_REPAY,
CANNOT_BORROW_ASSET
}
enumFailureInfo {
ACCEPT_ADMIN_PENDING_ADMIN_CHECK,
ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,
EXIT_MARKET_BALANCE_OWED,
EXIT_MARKET_REJECTION,
SET_CLOSE_FACTOR_OWNER_CHECK,
SET_CLOSE_FACTOR_VALIDATION,
SET_COLLATERAL_FACTOR_OWNER_CHECK,
SET_COLLATERAL_FACTOR_NO_EXISTS,
SET_COLLATERAL_FACTOR_VALIDATION,
SET_COLLATERAL_FACTOR_WITHOUT_PRICE,
SET_IMPLEMENTATION_OWNER_CHECK,
SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,
SET_LIQUIDATION_INCENTIVE_VALIDATION,
SET_MAX_ASSETS_OWNER_CHECK,
SET_PENDING_ADMIN_OWNER_CHECK,
SET_PENDING_IMPLEMENTATION_OWNER_CHECK,
SET_PRICE_ORACLE_OWNER_CHECK,
SUPPORT_MARKET_EXISTS,
SUPPORT_MARKET_OWNER_CHECK,
SET_PAUSE_GUARDIAN_OWNER_CHECK
}
/**
* @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary
* contract-specific code that enables us to report opaque error codes from upgradeable contracts.
**/eventFailure(uinterror, uint info, uint detail);
/**
* @dev use this when reporting a known error from the money market or a non-upgradeable collaborator
*/functionfail(Error err, FailureInfo info) internalreturns (uint) {
emit Failure(uint(err), uint(info), 0);
returnuint(err);
}
/**
* @dev use this when reporting an opaque error from an upgradeable collaborator contract
*/functionfailOpaque(Error err, FailureInfo info, uint opaqueError) internalreturns (uint) {
emit Failure(uint(err), uint(info), opaqueError);
returnuint(err);
}
}
contractTokenErrorReporter{
uintpublicconstant NO_ERROR =0; // support legacy return codeserrorTransferComptrollerRejection(uint256 errorCode);
errorTransferNotAllowed();
errorTransferNotEnough();
errorTransferTooMuch();
errorMintComptrollerRejection(uint256 errorCode);
errorMintFreshnessCheck();
errorRedeemComptrollerRejection(uint256 errorCode);
errorRedeemFreshnessCheck();
errorRedeemTransferOutNotPossible();
errorBorrowComptrollerRejection(uint256 errorCode);
errorBorrowFreshnessCheck();
errorBorrowCashNotAvailable();
errorRepayBorrowComptrollerRejection(uint256 errorCode);
errorRepayBorrowFreshnessCheck();
errorLiquidateComptrollerRejection(uint256 errorCode);
errorLiquidateFreshnessCheck();
errorLiquidateCollateralFreshnessCheck();
errorLiquidateAccrueBorrowInterestFailed(uint256 errorCode);
errorLiquidateAccrueCollateralInterestFailed(uint256 errorCode);
errorLiquidateLiquidatorIsBorrower();
errorLiquidateCloseAmountIsZero();
errorLiquidateCloseAmountIsUintMax();
errorLiquidateRepayBorrowFreshFailed(uint256 errorCode);
errorLiquidateSeizeComptrollerRejection(uint256 errorCode);
errorLiquidateSeizeLiquidatorIsBorrower();
errorAcceptAdminPendingAdminCheck();
errorSetComptrollerOwnerCheck();
errorSetPendingAdminOwnerCheck();
errorSetReserveFactorAdminCheck();
errorSetReserveFactorFreshCheck();
errorSetReserveFactorBoundsCheck();
errorAddReservesFactorFreshCheck(uint256 actualAddAmount);
errorReduceReservesAdminCheck();
errorReduceReservesFreshCheck();
errorReduceReservesCashNotAvailable();
errorReduceReservesCashValidation();
errorSetInterestRateModelOwnerCheck();
errorSetInterestRateModelFreshCheck();
errorSetStakedGlpAddressOwnerCheck();
errorSignalTransferOwnerCheck();
errorSetAutoCompoundOwnerCheck();
}
Contract Source Code
File 7 of 11: IERC721Receiver.sol
// SPDX-License-Identifier: BSD-3-Clausepragmasolidity ^0.8.10;/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/interfaceIERC721Receiver{
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/functiononERC721Received(address operator,
addressfrom,
uint256 tokenId,
bytescalldata data
) externalreturns (bytes4);
}
// SPDX-License-Identifier: BSD-3-Clausepragmasolidity ^0.8.10;/**
* @title Compound's InterestRateModel Interface
* @author Compound
*/abstractcontractInterestRateModel{
/// @notice Indicator that this is an InterestRateModel contract (for inspection)boolpublicconstant isInterestRateModel =true;
/**
* @notice Calculates the current borrow interest rate per block
* @param cash The total amount of cash the market has
* @param borrows The total amount of borrows the market has outstanding
* @param reserves The total amount of reserves the market has
* @return The borrow rate per block (as a percentage, and scaled by 1e18)
*/functiongetBorrowRate(uint cash, uint borrows, uint reserves) virtualexternalviewreturns (uint);
/**
* @notice Calculates the current supply interest rate per block
* @param cash The total amount of cash the market has
* @param borrows The total amount of borrows the market has outstanding
* @param reserves The total amount of reserves the market has
* @param reserveFactorMantissa The current reserve factor the market has
* @return The supply rate per block (as a percentage, and scaled by 1e18)
*/functiongetSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtualexternalviewreturns (uint);
}