From a05b865b6d0f20d12984fd85202a6c127ff9ff5d Mon Sep 17 00:00:00 2001 From: Mubaris NK Date: Sun, 25 Apr 2021 10:23:58 +0530 Subject: [PATCH] Staked AAVE connector --- .../connectors/aave/staked-aave/events.sol | 15 +++ .../connectors/aave/staked-aave/helpers.sol | 78 +++++++++++ .../connectors/aave/staked-aave/interface.sol | 16 +++ .../connectors/aave/staked-aave/main.sol | 123 ++++++++++++++++++ 4 files changed, 232 insertions(+) create mode 100644 contracts/mainnet/connectors/aave/staked-aave/events.sol create mode 100644 contracts/mainnet/connectors/aave/staked-aave/helpers.sol create mode 100644 contracts/mainnet/connectors/aave/staked-aave/interface.sol create mode 100644 contracts/mainnet/connectors/aave/staked-aave/main.sol diff --git a/contracts/mainnet/connectors/aave/staked-aave/events.sol b/contracts/mainnet/connectors/aave/staked-aave/events.sol new file mode 100644 index 00000000..79bd13ef --- /dev/null +++ b/contracts/mainnet/connectors/aave/staked-aave/events.sol @@ -0,0 +1,15 @@ +pragma solidity ^0.7.0; + +contract Events { + event LogClaim(uint amt, uint getId, uint setId); + event LogStake(uint amt, uint getId, uint setId); + event LogCooldown(); + event LogRedeem(uint amt, uint getId, uint setId); + event LogDelegate( + address delegatee, + bool delegateAave, + bool delegateStkAave, + uint8 aaveDelegationType, + uint8 stkAaveDelegationType + ); +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/aave/staked-aave/helpers.sol b/contracts/mainnet/connectors/aave/staked-aave/helpers.sol new file mode 100644 index 00000000..0426ea4b --- /dev/null +++ b/contracts/mainnet/connectors/aave/staked-aave/helpers.sol @@ -0,0 +1,78 @@ +pragma solidity ^0.7.0; + +import { DSMath } from "../../../common/math.sol"; +import { Basic } from "../../../common/basic.sol"; +import { StakedAaveInterface, AaveInterface } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + + enum DelegationType {VOTING_POWER, PROPOSITION_POWER, BOTH} + + /** + * @dev Staked Aave Token + */ + StakedAaveInterface internal constant stkAave = StakedAaveInterface(0x4da27a545c0c5B758a6BA100e3a049001de870f5); + + /** + * @dev Aave Token + */ + AaveInterface internal constant aave = AaveInterface(0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9); + + function _delegateAave(address _delegatee, DelegationType _type) internal { + if (_type == DelegationType.BOTH) { + require( + aave.getDelegateeByType(address(this), 0) != _delegatee, + "already-delegated" + ); + require( + aave.getDelegateeByType(address(this), 1) != _delegatee, + "already-delegated" + ); + + aave.delegate(_delegatee); + } else if (_type == DelegationType.VOTING_POWER) { + require( + aave.getDelegateeByType(address(this), 0) != _delegatee, + "already-delegated" + ); + + aave.delegateByType(_delegatee, 0); + } else { + require( + aave.getDelegateeByType(address(this), 1) != _delegatee, + "already-delegated" + ); + + aave.delegateByType(_delegatee, 1); + } + } + + function _delegateStakedAave(address _delegatee, DelegationType _type) internal { + if (_type == DelegationType.BOTH) { + require( + stkAave.getDelegateeByType(address(this), 0) != _delegatee, + "already-delegated" + ); + require( + stkAave.getDelegateeByType(address(this), 1) != _delegatee, + "already-delegated" + ); + + stkAave.delegate(_delegatee); + } else if (_type == DelegationType.VOTING_POWER) { + require( + stkAave.getDelegateeByType(address(this), 0) != _delegatee, + "already-delegated" + ); + + stkAave.delegateByType(_delegatee, 0); + } else { + require( + stkAave.getDelegateeByType(address(this), 1) != _delegatee, + "already-delegated" + ); + + stkAave.delegateByType(_delegatee, 1); + } + } +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/aave/staked-aave/interface.sol b/contracts/mainnet/connectors/aave/staked-aave/interface.sol new file mode 100644 index 00000000..6f8e3a04 --- /dev/null +++ b/contracts/mainnet/connectors/aave/staked-aave/interface.sol @@ -0,0 +1,16 @@ +pragma solidity ^0.7.0; + +import { TokenInterface } from "../../../common/interfaces.sol"; + +interface AaveInterface is TokenInterface { + function delegate(address delegatee) external; + function delegateByType(address delegatee, uint8 delegationType) external; + function getDelegateeByType(address delegator, uint8 delegationType) external view returns (address); +} + +interface StakedAaveInterface is AaveInterface { + function stake(address onBehalfOf, uint256 amount) external; + function redeem(address to, uint256 amount) external; + function cooldown() external; + function claimRewards(address to, uint256 amount) external; +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/aave/staked-aave/main.sol b/contracts/mainnet/connectors/aave/staked-aave/main.sol new file mode 100644 index 00000000..ffd7c5f6 --- /dev/null +++ b/contracts/mainnet/connectors/aave/staked-aave/main.sol @@ -0,0 +1,123 @@ +pragma solidity ^0.7.0; + +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; + +abstract contract AaveResolver is Helpers, Events { + + /** + * @dev Claim Accrued AAVE. + * @notice Claim Accrued AAVE Token rewards. + * @param amount The amount of rewards to claim. uint(-1) for max. + * @param getId ID to retrieve amount. + * @param setId ID stores the amount of tokens claimed. + */ + function claim( + uint256 amount, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amount); + + uint intialBal = aave.balanceOf(address(this)); + stkAave.claimRewards(address(this), _amt); + uint finalBal = aave.balanceOf(address(this)); + _amt = sub(finalBal, intialBal); + + setUint(setId, _amt); + + _eventName = "LogClaim(uint256,uint256,uint256)"; + _eventParam = abi.encode(_amt, getId, setId); + } + + /** + * @dev Stake AAVE Token + * @notice Stake AAVE Token in Aave security module + * @param amount The amount of AAVE to stake. uint(-1) for max. + * @param getId ID to retrieve amount. + * @param setId ID stores the amount of tokens staked. + */ + function stake( + uint256 amount, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amount); + + _amt = _amt == uint(-1) ? aave.balanceOf(address(this)) : _amt; + stkAave.stake(address(this), _amt); + + setUint(setId, _amt); + + _eventName = "LogStake(uint256,uint256,uint256)"; + _eventParam = abi.encode(_amt, getId, setId); + } + + /** + * @dev Initiate cooldown to unstake + * @notice Initiate cooldown to unstake from Aave security module + */ + function cooldown() external payable returns (string memory _eventName, bytes memory _eventParam) { + require(stkAave.balanceOf(address(this)) > 0, "no-staking"); + + stkAave.cooldown(); + + _eventName = "LogCooldown()"; + } + + /** + * @dev Redeem tokens from Staked AAVE + * @notice Redeem AAVE tokens from Staked AAVE after cooldown period is over + * @param amount The amount of AAVE to redeem. uint(-1) for max. + * @param getId ID to retrieve amount. + * @param setId ID stores the amount of tokens redeemed. + */ + function redeem( + uint256 amount, + uint256 getId, + uint256 setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amount); + + uint intialBal = aave.balanceOf(address(this)); + stkAave.redeem(address(this), _amt); + uint finalBal = aave.balanceOf(address(this)); + _amt = sub(finalBal, intialBal); + + setUint(setId, _amt); + + _eventName = "LogRedeem(uint256,uint256,uint256)"; + _eventParam = abi.encode(_amt, getId, setId); + } + + /** + * @dev Delegate AAVE or stkAAVE + * @notice Delegate AAVE or stkAAVE + * @param delegatee The address of the delegatee + * @param delegateAave Whether to delegate Aave balance + * @param delegateStkAave Whether to delegate Staked Aave balance + * @param aaveDelegationType Aave delegation type. Voting power - 0, Proposition power - 1, Both - 2 + * @param stkAaveDelegationType Staked Aave delegation type. Values similar to aaveDelegationType + */ + function delegate( + address delegatee, + bool delegateAave, + bool delegateStkAave, + uint8 aaveDelegationType, + uint8 stkAaveDelegationType + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + require(delegateAave || delegateStkAave, "invalid-delegate"); + require(delegatee != address(0), "invalid-delegatee"); + + if (delegateAave) { + _delegateAave(delegatee, Helpers.DelegationType(aaveDelegationType)); + } + + if (delegateStkAave) { + _delegateStakedAave(delegatee, Helpers.DelegationType(stkAaveDelegationType)); + } + + _eventName = "LogDelegate(address,bool,bool,uint8,uint8)"; + _eventParam = abi.encode(delegatee, delegateAave, delegateStkAave, aaveDelegationType, stkAaveDelegationType); + } +} \ No newline at end of file