Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PROTOCOL-690: Feature/aave claim aave #454

Open
wants to merge 24 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion config/dapps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@ import { Tokens } from '../types/custom/config-types'

const mainnetDappAddresses: Tokens = {
aaveLendingPoolAddressProvider: '0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5',
aaveLendingPool: '0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9',
aaveStakeTokenAddress: '0x4da27a545c0c5b758a6ba100e3a049001de870f5',
aaveIncentivesControllerAddress: '0xd784927Ff2f95ba542BfC824c8a8a98F3495f6b5',
sushiswapV2RouterAddress: '0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F',
uniswapV2RouterAddress: '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D',
compoundComptrollerAddress: '0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b',
}

const polygonDappAddresses: Tokens = {
aaveLendingPoolAddressProvider: '0xd05e3E715d945B59290df0ae8eF85c1BdB684744',
aaveLendingPool: '0x8dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcf',
aaveRewardTokenAddress: '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270',
aaveIncentivesControllerAddress: '0x357D51124f59836DeD84c8a1730D72B749d8BC23',
sushiswapV2RouterAddress: '0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506',
uniswapV2RouterAddress: '0x0000000000000000000000000000000000000000',
compoundComptrollerAddress: '',
}

export const dapps: Record<string, Tokens> = {
Expand Down
109 changes: 109 additions & 0 deletions contracts/escrow/dapps/AaveClaimAaveFacet.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Contracts
import { DappMods } from "./DappMods.sol";
import { PausableMods } from "../../settings/pausable/PausableMods.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {
SafeERC20
} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

// Libraries
import { LibDapps } from "./libraries/LibDapps.sol";
import { LibEscrow, ILoansEscrow } from "../libraries/LibEscrow.sol";

// Interfaces
import { IAToken } from "../../shared/interfaces/IAToken.sol";
import {
IAaveIncentivesController
} from "../../shared/interfaces/IAaveIncentivesController.sol";
import { LibLoans } from "../../market/libraries/LibLoans.sol";

// Storage
import { LoanStatus } from "../../storage/market.sol";
import { IStakedAave } from "../../shared/interfaces/IStakedAave.sol";

contract AaveClaimAaveFacet is PausableMods, DappMods {
using SafeERC20 for IERC20;

/**
* @dev The address of Aave's Incentives controller Address on the deployed network
* @dev example - Aave's Incentives controller contract address on L1 mainnet or L2 polygon mainnet
*/
address public immutable INCENTIVES_CONTROLLER_ADDRESS;
address public immutable STAKE_TOKEN_ADDRESS;

/**
* @notice Sets the network relevant address for Aave's Incentives controller Address on protocol deployment.
* @param aaveIncentivesControllerAddress The immutable address of Aave's Incentives controller Address on the deployed network.
*/
constructor(
address aaveIncentivesControllerAddress,
address aaveStakeTokenAddress
) public {
INCENTIVES_CONTROLLER_ADDRESS = aaveIncentivesControllerAddress;
STAKE_TOKEN_ADDRESS = aaveStakeTokenAddress;
}

/**
@notice This event is emitted every time Aave deposit is invoked successfully.
@param borrower address of the loan borrower.
@param loanID ID of the loan.
*/
event AaveClaimed(address borrower, uint256 loanID);

/**
* @notice To claim AAVE call the {claimRewards} function on {AaveIncentivesController}.
* @param loanID id of the loan being used in the dapp
* @param amount amount of tokens to claim.
* @param tokenAddresses array of aave underlying assets on the lending pool
*/
function aaveClaimAave(
uint256 loanID,
uint256 amount,
address[] calldata tokenAddresses
) public paused("", false) onlyBorrower(loanID) {
bool loanUnavailable = LibLoans.loan(loanID).status >=
LoanStatus.Closed;
address user = loanUnavailable
? msg.sender
: address(LibEscrow.e(loanID));
bytes memory result = LibEscrow.e(loanID).callDapp(
address(INCENTIVES_CONTROLLER_ADDRESS),
abi.encodeWithSelector(
IAaveIncentivesController.claimRewards.selector,
tokenAddresses,
amount,
user
)
);

bytes memory unstake = LibEscrow.e(loanID).callDapp(
address(STAKE_TOKEN_ADDRESS),
abi.encodeWithSelector(IStakedAave.redeem.selector, user, amount)
);

if (loanUnavailable) {
for (uint256 index = 0; index < tokenAddresses.length; index++) {
LibEscrow.tokenUpdated(loanID, address(tokenAddresses[index]));
}
}

emit AaveClaimed(msg.sender, loanID);
}

/**
* @notice This function calculates the amount of aave tokens that can be redeemed.
* @param loanID id of the loan being used in the dapp
*/
function aaveCalculateAave(uint256 loanID) public view returns (uint256) {
IAaveIncentivesController conptroller = IAaveIncentivesController(
INCENTIVES_CONTROLLER_ADDRESS
);
uint256 result = conptroller.getUserUnclaimedRewards(
address(LibEscrow.e(loanID))
);
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,24 @@ import { PausableMods } from "../../settings/pausable/PausableMods.sol";
// Libraries
import { LibCompound } from "./libraries/LibCompound.sol";
import { LibEscrow } from "../libraries/LibEscrow.sol";
import { LibLoans } from "../../market/libraries/LibLoans.sol";
import {
AssetCTokenLib
} from "../../settings/asset/libraries/AssetCTokenLib.sol";
// Storage
import { LoanStatus } from "../../storage/market.sol";

// Interfaces
import { IComptroller } from "../../shared/interfaces/IComptroller.sol";
import { ICErc20 } from "../../shared/interfaces/ICErc20.sol";

contract CompoundClaimCompFacet is PausableMods, DappMods {
/**
* @notice This event is emitted every time Compound redeem is invoked successfully.
* @param holder address of escrow.
* @param borrower address of the loan borrower.
* @param loanID loan ID.
*/
event CompoundClaimed(address indexed holder, uint256 loanID);
event CompoundClaimed(address indexed borrower, uint256 loanID);

/**
* @dev The address of Compound's Comptroler Address Provider on the deployed network
Expand All @@ -35,20 +42,31 @@ contract CompoundClaimCompFacet is PausableMods, DappMods {
}

/**
* @notice To claim comp call the claim comp function on COMPTROLLER_ADDRESS_PROVIDER_ADDRESS.
* @notice To claim COMP call the {claimComp} function on COMPTROLLER_ADDRESS_PROVIDER_ADDRESS.
* @param loanID id of the loan being used in the dapp
* @param tokenAddress address of the token.
*/
function compoundClaimComp(uint256 loanID)
function compoundClaimComp(uint256 loanID, address tokenAddress)
public
paused("", false)
onlyBorrower(loanID)
{
address escrow = address(LibEscrow.e(loanID));
bool loanUnavailable = LibLoans.loan(loanID).status >=
LoanStatus.Closed;
address user = loanUnavailable
? msg.sender
: address(LibEscrow.e(loanID));
LibEscrow.e(loanID).callDapp(
address(COMPTROLLER_ADDRESS_PROVIDER_ADDRESS),
abi.encodeWithSignature("claimComp(address)", escrow)
abi.encodeWithSignature("claimComp(address)", user)
);
emit CompoundClaimed(escrow, loanID);

if (loanUnavailable) {
ICErc20 cToken = AssetCTokenLib.get(tokenAddress);
LibEscrow.tokenUpdated(loanID, address(cToken));
}

emit CompoundClaimed(msg.sender, loanID);
}

/**
Expand Down
57 changes: 57 additions & 0 deletions contracts/shared/interfaces/IAaveDistributionManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;

interface IAaveDistributionManager {
event AssetConfigUpdated(address indexed asset, uint256 emission);
event AssetIndexUpdated(address indexed asset, uint256 index);
event UserIndexUpdated(
address indexed user,
address indexed asset,
uint256 index
);
event DistributionEndUpdated(uint256 newDistributionEnd);

/**
* @dev Sets the end date for the distribution
* @param distributionEnd The end date timestamp
**/
function setDistributionEnd(uint256 distributionEnd) external;

/**
* @dev Gets the end date for the distribution
* @return The end of the distribution
**/
function getDistributionEnd() external view returns (uint256);

/**
* @dev for backwards compatibility with the previous DistributionManager used
* @return The end of the distribution
**/
function DISTRIBUTION_END() external view returns (uint256);

/**
* @dev Returns the data of an user on a distribution
* @param user Address of the user
* @param asset The address of the reference asset of the distribution
* @return The new index
**/
function getUserAssetData(address user, address asset)
external
view
returns (uint256);

/**
* @dev Returns the configuration of the distribution for a certain asset
* @param asset The address of the reference asset of the distribution
* @return The asset index, the emission per second and the last updated timestamp
**/
function getAssetData(address asset)
external
view
returns (
uint256,
uint256,
uint256
);
}
107 changes: 107 additions & 0 deletions contracts/shared/interfaces/IAaveIncentivesController.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

pragma experimental ABIEncoderV2;

import { IAaveDistributionManager } from "./IAaveDistributionManager.sol";

interface IAaveIncentivesController is IAaveDistributionManager {
event RewardsAccrued(address indexed user, uint256 amount);

event RewardsClaimed(
address indexed user,
address indexed to,
address indexed claimer,
uint256 amount
);

event ClaimerSet(address indexed user, address indexed claimer);

/**
* @dev Whitelists an address to claim the rewards on behalf of another address
* @param user The address of the user
* @param claimer The address of the claimer
*/
function setClaimer(address user, address claimer) external;

/**
* @dev Returns the whitelisted claimer for a certain address (0x0 if not set)
* @param user The address of the user
* @return The claimer address
*/
function getClaimer(address user) external view returns (address);

/**
* @dev Configure assets for a certain rewards emission
* @param assets The assets to incentivize
* @param emissionsPerSecond The emission for each asset
*/
function configureAssets(
address[] calldata assets,
uint256[] calldata emissionsPerSecond
) external;

/**
* @dev Called by the corresponding asset on any update that affects the rewards distribution
* @param asset The address of the user
* @param userBalance The balance of the user of the asset in the lending pool
* @param totalSupply The total supply of the asset in the lending pool
**/
function handleAction(
address asset,
uint256 userBalance,
uint256 totalSupply
) external;

/**
* @dev Returns the total of rewards of an user, already accrued + not yet accrued
* @param user The address of the user
* @return The rewards
**/
function getRewardsBalance(address[] calldata assets, address user)
external
view
returns (uint256);

/**
* @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards
* @param amount Amount of rewards to claim
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewards(
address[] calldata assets,
uint256 amount,
address to
) external returns (uint256);

/**
* @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must
* be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager
* @param amount Amount of rewards to claim
* @param user Address to check and claim rewards
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewardsOnBehalf(
address[] calldata assets,
uint256 amount,
address user,
address to
) external returns (uint256);

/**
* @dev returns the unclaimed rewards of the user
* @param user the address of the user
* @return the unclaimed user rewards
*/
function getUserUnclaimedRewards(address user)
external
view
returns (uint256);

/**
* @dev for backward compatibility with previous implementation of the Incentives controller
*/
function REWARD_TOKEN() external view returns (address);
}
Loading