diff --git a/src/interfaces/omni/IBalanceTracker.sol b/src/interfaces/omni/IBalanceTracker.sol new file mode 100644 index 0000000..c8c9bc2 --- /dev/null +++ b/src/interfaces/omni/IBalanceTracker.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BSL-1.1 +pragma solidity 0.8.25; + +/** + * @title IAssetBalanceReporter + * @notice Interface for reporting asset balances, providing information about token holdings. + */ +interface IBalanceTracker { + /** + * @notice Struct representing the balance of a specific asset + * @param token The address of the token + * @param amount The current balance of the token + */ + struct AssetBalance { + address token; + uint256 amount; + } + + /** + * @notice Retrieves the asset balances for a specific user + * @param user The address of the user to query + * @return An array of AssetBalance structs representing the user's token holdings + */ + function balancesOf(address user) external view returns (AssetBalance[] memory); +} diff --git a/src/interfaces/omni/IValidator.sol b/src/interfaces/omni/IValidator.sol new file mode 100644 index 0000000..e69de29 diff --git a/src/omni/VaultRateProvider.sol b/src/omni/VaultRateProvider.sol index 081fa35..af35241 100644 --- a/src/omni/VaultRateProvider.sol +++ b/src/omni/VaultRateProvider.sol @@ -8,11 +8,7 @@ import {OmniVault} from "./OmniVault.sol"; import {IRateProvider} from "../interfaces/omni/IRateProvider.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; import {IERC20Metadata} from "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; - - -interface ITvlModule { - function getTvl() external view returns (uint256); -} +import {IBalanceTracker} from "../interfaces/omni/IBalanceTracker.sol"; contract VaultRateProvider is AccessControlUpgradeable { @@ -21,7 +17,7 @@ contract VaultRateProvider is AccessControlUpgradeable { bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE"); OmniVault public vault; - ITvlModule[] public tvlModules; + IBalanceTracker[] public balanceTrackers; IRateProvider public assetRateProvider; /** @@ -46,6 +42,39 @@ contract VaultRateProvider is AccessControlUpgradeable { unit = _unit; } + /** + * @notice Updates the vault rate based on the total value of assets in the vault + * @dev This function calculates the total value of all assets tracked by the balance trackers + * and updates the vaultRate accordingly. It should be called periodically to keep the + * rate up-to-date. + */ + function updateVaultRate() external returns (uint256 _vaultRate){ + uint256 totalValue = 0; + uint256 totalSupply = vault.totalSupply(); + + for (uint256 i = 0; i < balanceTrackers.length; i++) { + IBalanceTracker.AssetBalance[] memory balances = balanceTrackers[i].balancesOf(address(vault)); + for (uint256 j = 0; j < balances.length; j++) { + address asset = balances[j].token; + uint256 amount = balances[j].amount; + uint256 assetValue = assetRateProvider.convert(asset, amount); + totalValue += assetValue; + } + } + + if (totalSupply > 0) { + _vaultRate = Math.mulDiv(totalValue, unit, totalSupply, Math.Rounding.Floor); + } else { + _vaultRate = unit; // If there's no supply, set the rate to 1:1 + } + + vaultRate = _vaultRate; + + emit VaultRateUpdated(vaultRate); + } + + event VaultRateUpdated(uint256 newRate); + function rate(address asset) public view returns (uint256) { uint256 unitOfAccountRateForAsset = assetRateProvider.rate(asset);