// SPDX-License-Identifier: MIT /** *Submitted for verification at Etherscan.io on 2020-09-18 */ pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/math/SafeMath.sol"; import "../interfaces/IFactory.sol"; interface IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint256); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); function owner() external view returns (address); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } library BoringERC20 { function returnDataToString(bytes memory data) internal pure returns (string memory) { if (data.length >= 64) { return abi.decode(data, (string)); } else if (data.length == 32) { uint8 i = 0; while (i < 32 && data[i] != 0) { i++; } bytes memory bytesArray = new bytes(i); for (i = 0; i < 32 && data[i] != 0; i++) { bytesArray[i] = data[i]; } return string(bytesArray); } else { return "???"; } } function symbol(IERC20 token) internal view returns (string memory) { (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x95d89b41)); return success ? returnDataToString(data) : "???"; } function name(IERC20 token) internal view returns (string memory) { (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x06fdde03)); return success ? returnDataToString(data) : "???"; } function decimals(IERC20 token) internal view returns (uint8) { (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x313ce567)); return success && data.length == 32 ? abi.decode(data, (uint8)) : 18; } function DOMAIN_SEPARATOR(IERC20 token) internal view returns (bytes32) { (bool success, bytes memory data) = address(token).staticcall{gas: 10000}(abi.encodeWithSelector(0x3644e515)); return success && data.length == 32 ? abi.decode(data, (bytes32)) : bytes32(0); } function nonces(IERC20 token, address owner) internal view returns (uint256) { (bool success, bytes memory data) = address(token).staticcall{gas: 5000}( abi.encodeWithSelector(0x7ecebe00, owner) ); // Use max uint256 to signal failure to retrieve nonce (probably not supported) return success && data.length == 32 ? abi.decode(data, (uint256)) : uint256(-1); } } interface IMasterChef { function BONUS_MULTIPLIER() external view returns (uint256); function devaddr() external view returns (address); function owner() external view returns (address); function startTimestamp() external view returns (uint256); function joe() external view returns (address); function joePerSec() external view returns (uint256); function totalAllocPoint() external view returns (uint256); function poolLength() external view returns (uint256); function poolInfo(uint256 nr) external view returns ( address, uint256, uint256, uint256 ); function userInfo(uint256 nr, address who) external view returns (uint256, uint256); function pendingTokens(uint256 pid, address who) external view returns ( uint256, address, string memory, uint256 ); } interface IPair is IERC20 { function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns ( uint112, uint112, uint32 ); } contract BoringCryptoTokenScanner { using SafeMath for uint256; struct Balance { address token; uint256 balance; } struct BalanceFull { address token; uint256 balance; uint256 rate; } struct TokenInfo { address token; uint256 decimals; string name; string symbol; } function getTokenInfo(address[] calldata addresses) public view returns (TokenInfo[] memory) { TokenInfo[] memory infos = new TokenInfo[](addresses.length); for (uint256 i = 0; i < addresses.length; i++) { IERC20 token = IERC20(addresses[i]); infos[i].token = address(token); infos[i].name = token.name(); infos[i].symbol = token.symbol(); infos[i].decimals = token.decimals(); } return infos; } function findBalances(address who, address[] calldata addresses) public view returns (Balance[] memory) { uint256 balanceCount; for (uint256 i = 0; i < addresses.length; i++) { if (IERC20(addresses[i]).balanceOf(who) > 0) { balanceCount++; } } Balance[] memory balances = new Balance[](balanceCount); balanceCount = 0; for (uint256 i = 0; i < addresses.length; i++) { IERC20 token = IERC20(addresses[i]); uint256 balance = token.balanceOf(who); if (balance > 0) { balances[balanceCount].token = address(token); balances[balanceCount].balance = token.balanceOf(who); balanceCount++; } } return balances; } function getBalances( address who, address[] calldata addresses, IFactory factory, address currency ) public view returns (BalanceFull[] memory) { BalanceFull[] memory balances = new BalanceFull[](addresses.length); for (uint256 i = 0; i < addresses.length; i++) { IERC20 token = IERC20(addresses[i]); balances[i].token = address(token); balances[i].balance = token.balanceOf(who); IPair pair = IPair(factory.getPair(addresses[i], currency)); if (address(pair) != address(0)) { uint256 reserveCurrency; uint256 reserveToken; if (pair.token0() == currency) { (reserveCurrency, reserveToken, ) = pair.getReserves(); } else { (reserveToken, reserveCurrency, ) = pair.getReserves(); } balances[i].rate = (reserveToken * 1e18) / reserveCurrency; } } return balances; } struct Factory { IFactory factory; uint256 allPairsLength; address feeTo; address feeToSetter; } function getFactoryInfo(IFactory[] calldata addresses) public view returns (Factory[] memory) { Factory[] memory factories = new Factory[](addresses.length); for (uint256 i = 0; i < addresses.length; i++) { IFactory factory = addresses[i]; factories[i].factory = factory; factories[i].allPairsLength = factory.allPairsLength(); factories[i].feeTo = factory.feeTo(); factories[i].feeToSetter = factory.feeToSetter(); } return factories; } struct Pair { address token; address token0; address token1; } function getPairs( IFactory factory, uint256 fromID, uint256 toID ) public view returns (Pair[] memory) { if (toID == 0) { toID = factory.allPairsLength(); } Pair[] memory pairs = new Pair[](toID - fromID); for (uint256 id = fromID; id < toID; id++) { address token = factory.allPairs(id); uint256 i = id - fromID; pairs[i].token = token; pairs[i].token0 = IPair(token).token0(); pairs[i].token1 = IPair(token).token1(); } return pairs; } function findPairs( address who, IFactory factory, uint256 fromID, uint256 toID ) public view returns (Pair[] memory) { if (toID == 0) { toID = factory.allPairsLength(); } uint256 pairCount; for (uint256 id = fromID; id < toID; id++) { address token = factory.allPairs(id); if (IERC20(token).balanceOf(who) > 0) { pairCount++; } } Pair[] memory pairs = new Pair[](pairCount); pairCount = 0; for (uint256 id = fromID; id < toID; id++) { address token = factory.allPairs(id); uint256 balance = IERC20(token).balanceOf(who); if (balance > 0) { pairs[pairCount].token = token; pairs[pairCount].token0 = IPair(token).token0(); pairs[pairCount].token1 = IPair(token).token1(); pairCount++; } } return pairs; } struct PairFull { address token; address token0; address token1; uint256 reserve0; uint256 reserve1; uint256 totalSupply; uint256 balance; } function getPairsFull(address who, address[] calldata addresses) public view returns (PairFull[] memory) { PairFull[] memory pairs = new PairFull[](addresses.length); for (uint256 i = 0; i < addresses.length; i++) { address token = addresses[i]; pairs[i].token = token; pairs[i].token0 = IPair(token).token0(); pairs[i].token1 = IPair(token).token1(); (uint256 reserve0, uint256 reserve1, ) = IPair(token).getReserves(); pairs[i].reserve0 = reserve0; pairs[i].reserve1 = reserve1; pairs[i].balance = IERC20(token).balanceOf(who); } return pairs; } }