Skip to content

Latest commit

 

History

History
627 lines (497 loc) · 17.5 KB

CompoundStrategy.md

File metadata and controls

627 lines (497 loc) · 17.5 KB

CompoundStrategy.sol

View Source: contracts/core/liquidity/strategies/CompoundStrategy.sol

↗ Extends: ILendingStrategy, Recoverable

CompoundStrategy

Contract Members

Constants & Variables

//private members
mapping(bytes32 => uint256) private _counters;
mapping(bytes32 => uint256) private _depositTotal;
mapping(bytes32 => uint256) private _withdrawalTotal;
bytes32 private constant _KEY;

//public members
bytes32 public constant CNAME_STRATEGY_COMPOUND;
bytes32 public constant NS_DEPOSITS;
bytes32 public constant NS_WITHDRAWALS;
address public depositCertificate;
contract ICompoundERC20DelegatorLike public delegator;

Functions

function (IStore _s, ICompoundERC20DelegatorLike _delegator, address _compoundWrappedStablecoin) public nonpayable Recoverable 

Arguments

Name Type Description
_s IStore
_delegator ICompoundERC20DelegatorLike
_compoundWrappedStablecoin address
Source Code
constructor(
    IStore _s,
    ICompoundERC20DelegatorLike _delegator,
    address _compoundWrappedStablecoin
  ) Recoverable(_s) {
    depositCertificate = _compoundWrappedStablecoin;
    delegator = _delegator;
  }

getDepositAsset

function getDepositAsset() public view
returns(contract IERC20)

Arguments

Name Type Description
Source Code
function getDepositAsset() public view override returns (IERC20) {
    return IERC20(s.getStablecoinAddressInternal());
  }

getDepositCertificate

function getDepositCertificate() public view
returns(contract IERC20)

Arguments

Name Type Description
Source Code
function getDepositCertificate() public view override returns (IERC20) {
    return IERC20(depositCertificate);
  }

getInfo

Gets info of this strategy by cover key Warning: this function does not validate the cover key supplied.

function getInfo(bytes32 coverKey) external view
returns(info struct ILendingStrategy.LendingStrategyInfoType)

Arguments

Name Type Description
coverKey bytes32 Enter the cover key
Source Code
function getInfo(bytes32 coverKey) external view override returns (LendingStrategyInfoType memory info) {
    info.deposits = s.getUintByKey(_getDepositsKey(coverKey));
    info.withdrawals = s.getUintByKey(_getWithdrawalsKey(coverKey));
  }

_getCertificateBalance

function _getCertificateBalance() private view
returns(uint256)

Arguments

Name Type Description
Source Code
function _getCertificateBalance() private view returns (uint256) {
    return getDepositCertificate().balanceOf(address(this));
  }

_drain

function _drain(IERC20 asset) private nonpayable

Arguments

Name Type Description
asset IERC20
Source Code
function _drain(IERC20 asset) private {
    uint256 amount = asset.balanceOf(address(this));

    if (amount > 0) {
      asset.ensureTransfer(s.getTreasuryAddressInternal(), amount);

      emit Drained(asset, amount);
    }
  }

deposit

Deposits the tokens to Compound Ensure that you approve stablecoin before you call this function

function deposit(bytes32 coverKey, uint256 amount) external nonpayable nonReentrant 
returns(compoundWrappedStablecoinMinted uint256)

Arguments

Name Type Description
coverKey bytes32
amount uint256
Source Code
function deposit(bytes32 coverKey, uint256 amount) external override nonReentrant returns (uint256 compoundWrappedStablecoinMinted) {
    s.mustNotBePaused();
    s.senderMustBeProtocolMember();

    IVault vault = s.getVault(coverKey);

    if (amount == 0) {
      return 0;
    }

    IERC20 stablecoin = getDepositAsset();
    IERC20 compoundWrappedStablecoin = getDepositCertificate();

    require(stablecoin.balanceOf(address(vault)) >= amount, "Balance insufficient");

    // This strategy should never have token balances
    _drain(compoundWrappedStablecoin);
    _drain(stablecoin);

    // Transfer stablecoin to this contract; then approve and send it to delegator to mint compoundWrappedStablecoin
    vault.transferToStrategy(stablecoin, coverKey, getName(), amount);
    stablecoin.ensureApproval(address(delegator), amount);

    uint256 result = delegator.mint(amount);

    require(result == 0, "Compound delegator mint failed");

    // Check how many compoundWrappedStablecoin we received
    compoundWrappedStablecoinMinted = _getCertificateBalance();

    require(compoundWrappedStablecoinMinted > 0, "Minting cUS$ failed");

    // Immediately send compoundWrappedStablecoin to the original vault stablecoin came from
    compoundWrappedStablecoin.ensureApproval(address(vault), compoundWrappedStablecoinMinted);
    vault.receiveFromStrategy(compoundWrappedStablecoin, coverKey, getName(), compoundWrappedStablecoinMinted);

    s.addUintByKey(_getDepositsKey(coverKey), amount);

    _counters[coverKey] += 1;
    _depositTotal[coverKey] += amount;

    emit LogDeposit(getName(), _counters[coverKey], amount, compoundWrappedStablecoinMinted, _depositTotal[coverKey], _withdrawalTotal[coverKey]);
    emit Deposited(coverKey, address(vault), amount, compoundWrappedStablecoinMinted);
  }

withdraw

Redeems compoundWrappedStablecoin from Compound to receive stablecoin Ensure that you approve compoundWrappedStablecoin before you call this function

function withdraw(bytes32 coverKey) external nonpayable nonReentrant 
returns(stablecoinWithdrawn uint256)

Arguments

Name Type Description
coverKey bytes32
Source Code
function withdraw(bytes32 coverKey) external virtual override nonReentrant returns (uint256 stablecoinWithdrawn) {
    s.mustNotBePaused();
    s.senderMustBeProtocolMember();
    IVault vault = s.getVault(coverKey);

    IERC20 stablecoin = getDepositAsset();
    IERC20 compoundWrappedStablecoin = getDepositCertificate();

    // This strategy should never have token balances without any exception, especially `compoundWrappedStablecoin` and `stablecoin`
    _drain(compoundWrappedStablecoin);
    _drain(stablecoin);

    uint256 compoundWrappedStablecoinRedeemed = compoundWrappedStablecoin.balanceOf(address(vault));

    if (compoundWrappedStablecoinRedeemed == 0) {
      return 0;
    }

    // Transfer compoundWrappedStablecoin to this contract; then approve and send it to delegator to redeem stablecoin
    vault.transferToStrategy(compoundWrappedStablecoin, coverKey, getName(), compoundWrappedStablecoinRedeemed);
    compoundWrappedStablecoin.ensureApproval(address(delegator), compoundWrappedStablecoinRedeemed);
    uint256 result = delegator.redeem(compoundWrappedStablecoinRedeemed);

    require(result == 0, "Compound delegator redeem failed");

    // Check how many stablecoin we received
    stablecoinWithdrawn = stablecoin.balanceOf(address(this));

    require(stablecoinWithdrawn > 0, "Redeeming cUS$ failed");

    // Immediately send stablecoin to the vault compoundWrappedStablecoin came from
    stablecoin.ensureApproval(address(vault), stablecoinWithdrawn);
    vault.receiveFromStrategy(stablecoin, coverKey, getName(), stablecoinWithdrawn);

    s.addUintByKey(_getWithdrawalsKey(coverKey), stablecoinWithdrawn);

    _counters[coverKey] += 1;
    _withdrawalTotal[coverKey] += stablecoinWithdrawn;

    emit LogWithdrawal(getName(), _counters[coverKey], stablecoinWithdrawn, compoundWrappedStablecoinRedeemed, _depositTotal[coverKey], _withdrawalTotal[coverKey]);
    emit Withdrawn(coverKey, address(vault), stablecoinWithdrawn, compoundWrappedStablecoinRedeemed);
  }

_getDepositsKey

Hash key of the Compound deposits for the given cover. Warning: this function does not validate the cover key supplied.

function _getDepositsKey(bytes32 coverKey) private pure
returns(bytes32)

Arguments

Name Type Description
coverKey bytes32 Enter cover key
Source Code
function _getDepositsKey(bytes32 coverKey) private pure returns (bytes32) {
    return keccak256(abi.encodePacked(_KEY, coverKey, NS_DEPOSITS));
  }

_getWithdrawalsKey

Hash key of the Compound withdrawal for the given cover. Warning: this function does not validate the cover key supplied.

function _getWithdrawalsKey(bytes32 coverKey) private pure
returns(bytes32)

Arguments

Name Type Description
coverKey bytes32 Enter cover key
Source Code
function _getWithdrawalsKey(bytes32 coverKey) private pure returns (bytes32) {
    return keccak256(abi.encodePacked(_KEY, coverKey, NS_WITHDRAWALS));
  }

getWeight

function getWeight() external pure
returns(uint256)

Arguments

Name Type Description
Source Code
function getWeight() external pure override returns (uint256) {
    return 10_000; // 100%
  }

getKey

function getKey() external pure
returns(bytes32)

Arguments

Name Type Description
Source Code
function getKey() external pure override returns (bytes32) {
    return _KEY;
  }

version

Version number of this contract

function version() external pure
returns(bytes32)

Arguments

Name Type Description
Source Code
function version() external pure override returns (bytes32) {
    return "v0.1";
  }

getName

Name of this contract

function getName() public pure
returns(bytes32)

Arguments

Name Type Description
Source Code
function getName() public pure override returns (bytes32) {
    return CNAME_STRATEGY_COMPOUND;
  }

Contracts