//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IBPool {
function getCurrentTokens() external returns (address[] memory);
function getDenormalizedWeight(address token) external returns (uint);
function getSwapFee() external returns (uint);
function getBalance(address token) external returns (uint);
}
interface IERC20 {
function decimals() external view returns (uint8);
}
/**
* @dev This contract is not meant to be deployed. Instead, use a static call with the
* deployment bytecode as payload.
*/
contract BalancerDataSync {
struct PoolData {
address[] tokens;
uint8[] decimals;
uint256[] liquidity;
uint256[] weights;
uint32 fee;
}
constructor(address[] memory pools) {
PoolData[] memory allPoolData = new PoolData[](pools.length);
for (uint256 i = 0; i < pools.length; ++i) {
address poolAddress = pools[i];
if (codeSizeIsZero(poolAddress)) continue;
PoolData memory poolData;
// Get the tokens
address[] memory tokens = IBPool(poolAddress).getCurrentTokens();
uint8[] memory decimals = new uint8[](tokens.length);
uint256[] memory liquidity = new uint256[](tokens.length);
uint256[] memory weights = new uint256[](tokens.length);
for (uint256 j = 0; j < tokens.length; ++j) {
if (codeSizeIsZero(tokens[j])) {
continue;
}
}
// Grab the decimals/liquidity
for (uint256 j = 0; j < tokens.length; ++j) {
uint8 tokenDecimals = getTokenDecimals(tokens[j]);
if (tokenDecimals == 0) {
continue;
} else {
decimals[j] = tokenDecimals;
}
weights[j] = IBPool(poolAddress).getDenormalizedWeight(
tokens[j]
);
liquidity[j] = IBPool(poolAddress).getBalance(tokens[j]);
}
// Grab the swap fee
poolData.fee = uint32(IBPool(poolAddress).getSwapFee());
poolData.tokens = tokens;
poolData.decimals = decimals;
poolData.liquidity = liquidity;
poolData.weights = weights;
allPoolData[i] = poolData;
}
bytes memory _abiEncodedData = abi.encode(allPoolData);
assembly {
// Return from the start of the data (discarding the original data address)
// up to the end of the memory used
let dataStart := add(_abiEncodedData, 0x20)
return(dataStart, sub(msize(), dataStart))
}
}
function getTokenDecimals(address token) internal returns (uint8) {
(bool success, bytes memory data) = token.call(
abi.encodeWithSignature("decimals()")
);
if (success) {
uint256 decimals;
if (data.length == 32) {
(decimals) = abi.decode(data, (uint256));
if (decimals == 0 || decimals > 255) {
return 0;
} else {
return uint8(decimals);
}
} else {
return 0;
}
} else {
return 0;
}
}
function codeSizeIsZero(address target) internal view returns (bool) {
if (target.code.length == 0) {
return true;
} else {
return false;
}
}
}