aave-protocol-v2/contracts/misc/WalletBalanceProvider.sol

113 lines
3.4 KiB
Solidity
Raw Normal View History

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
2020-06-20 23:40:03 +00:00
import '@openzeppelin/contracts/utils/Address.sol';
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
2020-06-20 23:40:03 +00:00
import '../configuration/LendingPoolAddressesProvider.sol';
import '../lendingpool/LendingPool.sol';
2020-07-10 09:20:15 +00:00
import '../libraries/UniversalERC20.sol';
/**
2020-06-20 23:40:03 +00:00
* @title WalletBalanceProvider contract
* @author Aave, influenced by https://github.com/wbobeirne/eth-balance-checker/blob/master/contracts/BalanceChecker.sol
* @notice Implements a logic of getting multiple tokens balance for one user address
* @dev NOTE: THIS CONTRACT IS NOT USED WITHIN THE AAVE PROTOCOL. It's an accessory contract used to reduce the number of calls
* towards the blockchain from the Aave backend.
**/
contract WalletBalanceProvider {
2020-06-20 23:40:03 +00:00
using Address for address payable;
using Address for address;
2020-07-10 09:20:15 +00:00
using UniversalERC20 for IERC20;
2020-06-20 23:40:03 +00:00
LendingPoolAddressesProvider provider;
2020-06-20 23:40:03 +00:00
constructor(LendingPoolAddressesProvider _provider) public {
provider = _provider;
}
2020-06-20 23:40:03 +00:00
/**
@dev Fallback function, don't accept any ETH
**/
2020-06-20 23:40:03 +00:00
receive() external payable {
//only contracts can send ETH to the core
require(msg.sender.isContract(), '22');
}
2020-06-20 23:40:03 +00:00
/**
@dev Check the token balance of a wallet in a token contract
Returns the balance of the token for user. Avoids possible errors:
- return 0 on non-contract address
**/
2020-06-20 23:40:03 +00:00
function balanceOf(address _user, address _token) public view returns (uint256) {
// check if token is actually a contract
if (_token.isContract()) {
return IERC20(_token).balanceOf(_user);
} else {
return 0;
}
}
2020-07-10 09:20:15 +00:00
/**
* @notice Fetches, for a list of _users and _tokens (ETH included with mock address), the balances
* @param _users The list of users
* @param _tokens The list of tokens
* @return And array with the concatenation of, for each user, his/her balances
**/
2020-06-20 23:40:03 +00:00
function batchBalanceOf(address[] memory _users, address[] memory _tokens)
public
view
returns (uint256[] memory)
{
uint256[] memory balances = new uint256[](_users.length * _tokens.length);
for (uint256 i = 0; i < _users.length; i++) {
for (uint256 j = 0; j < _tokens.length; j++) {
uint256 _offset = i * _tokens.length;
2020-07-10 09:20:15 +00:00
if (IERC20(_tokens[j]).isETH()) {
2020-06-20 23:40:03 +00:00
balances[_offset + j] = _users[i].balance; // ETH balance
} else {
2020-06-20 23:40:03 +00:00
if (!_tokens[j].isContract()) {
revert('INVALID_TOKEN');
} else {
balances[_offset + j] = balanceOf(_users[i], _tokens[j]);
}
}
2020-06-20 23:40:03 +00:00
}
}
2020-06-20 23:40:03 +00:00
return balances;
}
2020-07-10 09:20:15 +00:00
2020-06-20 23:40:03 +00:00
/**
@dev provides balances of user wallet for all reserves available on the pool
*/
2020-06-20 23:40:03 +00:00
function getUserWalletBalances(address _user)
public
view
returns (address[] memory, uint256[] memory)
{
LendingPool pool = LendingPool(payable(provider.getLendingPool()));
address[] memory reserves = pool.getReserves();
uint256[] memory balances = new uint256[](reserves.length);
for (uint256 j = 0; j < reserves.length; j++) {
(, , , , , , , , bool isActive,) = pool.getReserveConfigurationData(reserves[j]);
2020-06-20 23:40:03 +00:00
if (!isActive) {
balances[j] = 0;
continue;
}
2020-07-10 09:20:15 +00:00
if (IERC20(reserves[j]).isETH()) {
2020-06-20 23:40:03 +00:00
balances[j] = balanceOf(_user, reserves[j]);
} else {
balances[j] = _user.balance; // ETH balance
}
}
2020-06-20 23:40:03 +00:00
return (reserves, balances);
}
}