From e3f13451b2364dc0a3d7b522c9a297b16943f5df Mon Sep 17 00:00:00 2001 From: EREN Date: Fri, 29 Nov 2024 02:37:19 +0900 Subject: [PATCH] add BeefyV2AppMulticall and script to deploy it --- contracts/BIFI/infra/BeefyV2AppMulticall.sol | 285 +++++++++++++++++++ package.json | 1 + scripts/infra/deployAppMulticall.js | 21 ++ 3 files changed, 307 insertions(+) create mode 100644 contracts/BIFI/infra/BeefyV2AppMulticall.sol create mode 100644 scripts/infra/deployAppMulticall.js diff --git a/contracts/BIFI/infra/BeefyV2AppMulticall.sol b/contracts/BIFI/infra/BeefyV2AppMulticall.sol new file mode 100644 index 00000000..e5c1c9aa --- /dev/null +++ b/contracts/BIFI/infra/BeefyV2AppMulticall.sol @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.4; + +interface IToken { + function allowance(address, address) external view returns (uint256); + function getEthBalance(address) external view returns (uint256); + function balanceOf(address) external view returns (uint256); +} + +interface IBeefyStrategy { + function paused() external view returns (bool); +} + +interface IBeefyVault { + function balance() external view returns (uint256); + function getPricePerFullShare() external view returns (uint256); + function strategy() external view returns (IBeefyStrategy); +} + +interface IBeefyCowVault { + function balances() external view returns (uint256, uint256); + function strategy() external view returns (IBeefyStrategy); +} + +interface IBeefyBoost { + function totalSupply() external view returns (uint256); + function periodFinish() external view returns (uint256); + function rewardRate() external view returns (uint256); + function balanceOf(address) external view returns (uint256); + function earned(address) external view returns (uint256); + function isPreStake() external view returns (bool); +} + +interface IBeefyBoostV2 { + function balanceOf(address) external view returns (uint256); + function earned(address) external view returns (address[] memory, uint256[] memory); +} + +interface IBeefyMultiRewardPool { + function totalSupply() external view returns (uint256); + function rewardsLength() external view returns (uint256); + function earned(address) external view returns (address[] memory, uint256[] memory); + function rewardInfo(uint256) external view returns (address, uint256, uint256, uint256, uint256); +} + +struct BoostInfo { + uint256 totalSupply; + uint256 rewardRate; + uint256 periodFinish; + bool isPreStake; +} + +struct VaultInfo { + uint256 balance; + uint256 pricePerFullShare; + address strategy; + bool paused; +} + +struct CowVaultInfo { + uint256 token0Balance; + uint256 token1Balance; + address strategy; + bool paused; +} + +struct GovVaultInfo { + uint256 totalSupply; +} + +struct RewardInfo { + address rewardAddress; + uint256 rate; + uint256 periodFinish; +} + +struct GovVaultMultiInfo { + uint256 totalSupply; + RewardInfo[] rewards; +} + +struct GovVaultBalanceInfo { + uint256 balance; + uint256 rewards; +} + +struct BoostBalanceInfo { + uint256 balance; + uint256 rewards; +} + +struct BoostBalanceInfoV2 { + uint256 balance; + address[] rewardTokens; + uint256[] rewards; +} + +struct AllowanceInfo { + uint[] allowances; +} + +contract BeefyV2AppMulticall { + function getVaultInfo(address[] calldata vaults) external view returns (VaultInfo[] memory) { + VaultInfo[] memory results = new VaultInfo[](vaults.length); + + for (uint i = 0; i < vaults.length; i++) { + IBeefyVault vault = IBeefyVault(vaults[i]); + IBeefyStrategy strat = vault.strategy(); + bool paused; + try strat.paused() returns (bool _paused) { + paused = _paused; + } catch { + paused = false; + } + results[i] = VaultInfo(vault.balance(), vault.getPricePerFullShare(), address(strat), paused); + } + + return results; + } + + function getCowVaultInfo(address[] calldata vaults) external view returns (CowVaultInfo[] memory) { + CowVaultInfo[] memory results = new CowVaultInfo[](vaults.length); + + for (uint i = 0; i < vaults.length; i++) { + IBeefyCowVault vault = IBeefyCowVault(vaults[i]); + IBeefyStrategy strat = vault.strategy(); + bool paused; + try strat.paused() returns (bool _paused) { + paused = _paused; + } catch { + paused = false; + } + (uint256 balance0, uint256 balance1) = vault.balances(); + results[i] = CowVaultInfo(balance0, balance1, address(strat), paused); + } + + return results; + } + + function getBoostInfo(address[] calldata boosts) external view returns (BoostInfo[] memory) { + BoostInfo[] memory results = new BoostInfo[](boosts.length); + + for (uint i = 0; i < boosts.length; i++) { + IBeefyBoost boost = IBeefyBoost(boosts[i]); + uint256 periodFinish = boost.periodFinish(); + bool isPreStake; + try boost.isPreStake() returns (bool _isPreStake) { + isPreStake = _isPreStake; + } catch { + isPreStake = periodFinish == 0; + } + results[i] = BoostInfo(boost.totalSupply(), boost.rewardRate(), periodFinish, isPreStake); + } + + return results; + } + + function getGovVaultMultiBalance( + address[] calldata vaults, + address owner + ) external view returns (BoostBalanceInfoV2[] memory) { + BoostBalanceInfoV2[] memory results = new BoostBalanceInfoV2[](vaults.length); + for (uint i; i < vaults.length; i++) { + IBeefyBoostV2 boost = IBeefyBoostV2(vaults[i]); + (address[] memory rewardTokens, uint256[] memory rewards) = boost.earned(owner); + results[i] = BoostBalanceInfoV2(boost.balanceOf(owner), rewardTokens, rewards); + } + + return results; + } + + function getGovVaultInfo(address[] calldata govVaults) external view returns (GovVaultInfo[] memory) { + GovVaultInfo[] memory results = new GovVaultInfo[](govVaults.length); + + for (uint i = 0; i < govVaults.length; i++) { + IBeefyBoost govVault = IBeefyBoost(govVaults[i]); + results[i] = GovVaultInfo(govVault.totalSupply()); + } + + return results; + } + + function getGovVaultMultiInfo(address[] calldata govVaults) external view returns (GovVaultMultiInfo[] memory) { + GovVaultMultiInfo[] memory results = new GovVaultMultiInfo[](govVaults.length); + for (uint i = 0; i < govVaults.length; i++) { + IBeefyMultiRewardPool govVault = IBeefyMultiRewardPool(govVaults[i]); + + uint256 rewardCount; + try govVault.rewardsLength() returns (uint256 _length) { + rewardCount = _length; + } catch { + (address[] memory rewardTokens, ) = govVault.earned(0x0000000000000000000000000000000000000000); + rewardCount = rewardTokens.length; + } + + RewardInfo[] memory rewards = new RewardInfo[](rewardCount); + for (uint j = 0; j < rewardCount; j++) { + (address rewardAddress, uint256 periodFinish, , , uint256 rate) = govVault.rewardInfo(j); + rewards[j] = RewardInfo(rewardAddress, rate, periodFinish); + } + results[i] = GovVaultMultiInfo(govVault.totalSupply(), rewards); + } + + return results; + } + + function getTokenBalances(address[] calldata tokens, address owner) external view returns (uint256[] memory) { + uint256[] memory results = new uint256[](tokens.length); + for (uint i = 0; i < tokens.length; i++) { + IToken token = IToken(tokens[i]); + results[i] = token.balanceOf(owner); + } + return results; + } + + function getBoostOrGovBalance( + address[] calldata boosts, + address owner + ) external view returns (BoostBalanceInfo[] memory) { + BoostBalanceInfo[] memory results = new BoostBalanceInfo[](boosts.length); + for (uint i = 0; i < boosts.length; i++) { + IBeefyBoost boost = IBeefyBoost(boosts[i]); + results[i] = BoostBalanceInfo(boost.balanceOf(owner), boost.earned(owner)); + } + + return results; + } + + function getGovVaultBalance( + address[] calldata govVaults, + address owner + ) external view returns (GovVaultBalanceInfo[] memory) { + GovVaultBalanceInfo[] memory results = new GovVaultBalanceInfo[](govVaults.length); + for (uint i = 0; i < govVaults.length; i++) { + IBeefyBoost govVault = IBeefyBoost(govVaults[i]); + results[i] = GovVaultBalanceInfo(govVault.balanceOf(owner), govVault.earned(owner)); + } + + return results; + } + + function getAllowances( + address[] calldata tokens, + address[][] calldata spenders, + address owner + ) external view returns (AllowanceInfo[] memory) { + AllowanceInfo[] memory results = new AllowanceInfo[](tokens.length); + + for (uint i = 0; i < tokens.length; i++) { + IToken token = IToken(tokens[i]); + address[] calldata tokenSpenders = spenders[i]; + results[i] = AllowanceInfo(new uint256[](tokenSpenders.length)); + for (uint j = 0; j < tokenSpenders.length; j++) { + results[i].allowances[j] = token.allowance(owner, tokenSpenders[j]); + } + } + + return results; + } + + function getAllowancesFlat( + address[] calldata tokens, + address[][] calldata spenders, + address owner + ) external view returns (uint256[] memory) { + uint totalLength; + for (uint i = 0; i < spenders.length; i++) { + totalLength += spenders[i].length; + } + + uint256[] memory results = new uint256[](totalLength); + + uint maxAcum; + for (uint i = 0; i < tokens.length; i++) { + IToken token = IToken(tokens[i]); + address[] calldata tokenSpenders = spenders[i]; + for (uint j = 0; j < tokenSpenders.length; j++) { + results[maxAcum++] = token.allowance(owner, tokenSpenders[j]); + } + } + + return results; + } +} diff --git a/package.json b/package.json index 080d1290..02dd1b90 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "deploy:registry": "hardhat run scripts/infra/deployRegistry.ts --network", "deploy:autoHarvester": "hardhat run scripts/infra/deployAutoHarvester.ts --network", "deploy:contract": "hardhat run scripts/infra/deployContract.js --network", + "deploy:appMulticallv2": "hardhat run scripts/infra/deployAppMulticall.js --network", "zap": "hardhat run ./scripts/infra/zapViaAggregator.js --network", "setOracle": "hardhat run ./scripts/manage/setOracle.js --network", "setSwapInfo": "hardhat run ./scripts/manage/setSwapInfo.js --network", diff --git a/scripts/infra/deployAppMulticall.js b/scripts/infra/deployAppMulticall.js new file mode 100644 index 00000000..41a630ca --- /dev/null +++ b/scripts/infra/deployAppMulticall.js @@ -0,0 +1,21 @@ +const hardhat = require("hardhat"); + +const ethers = hardhat.ethers; + +async function main() { + await hardhat.run("compile"); + + const Multicall = await ethers.getContractFactory("BeefyV2AppMulticall"); + + const multicall = await Multicall.deploy(); + await multicall.deployed(); + + console.log("App v2 multicall deployed:", multicall.address); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + });