From a3d234b5700bf5586447f3b97264b8826a006089 Mon Sep 17 00:00:00 2001 From: 0x0Louis Date: Fri, 3 Nov 2023 19:06:33 +0100 Subject: [PATCH] fix FarmLensV2 --- contracts/traderjoe/FarmLensV2.sol | 26 ++++++++++++++++------- test/foundry/FarmLensV2.t.sol | 34 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 test/foundry/FarmLensV2.t.sol diff --git a/contracts/traderjoe/FarmLensV2.sol b/contracts/traderjoe/FarmLensV2.sol index f451321c..0580bdeb 100644 --- a/contracts/traderjoe/FarmLensV2.sol +++ b/contracts/traderjoe/FarmLensV2.sol @@ -247,13 +247,13 @@ contract FarmLensV2 { allFarmData.joePriceUsd = joePrice; allFarmData.totalAllocChefV2 = chefv2.totalAllocPoint(); - allFarmData.joePerSecChefV2 = chefv2.joePerSec(); + allFarmData.joePerSecChefV2 = _joePerSec(address(chefv2)); allFarmData.totalAllocChefV3 = chefv3.totalAllocPoint(); - allFarmData.joePerSecChefV3 = chefv3.joePerSec(); + allFarmData.joePerSecChefV3 = _joePerSec(address(chefv3)); allFarmData.totalAllocBMCJ = bmcj.totalAllocPoint(); - allFarmData.joePerSecBMCJ = bmcj.joePerSec(); + allFarmData.joePerSecBMCJ = _joePerSec(address(bmcj)); allFarmData.farmInfosV2 = _getMCFarmInfos(chefv2, avaxPrice, whitelistedPidsV2); allFarmData.farmInfosV3 = _getMCFarmInfos(chefv3, avaxPrice, whitelistedPidsV3); @@ -262,6 +262,16 @@ contract FarmLensV2 { return allFarmData; } + /// @notice Returns the joePerSec of a given MasterChef + /// @param mc The address of the MasterChef + function _joePerSec(address mc) internal view returns (uint256) { + try IMasterChef(mc).joePerSec() returns (uint256 joePerSec) { + return joePerSec; + } catch { + return 0; + } + } + /// @notice Returns the price of avax in Usd internally /// @return uint256 the avax price, scaled to 18 decimals function _getAvaxPrice() private view returns (uint256) { @@ -281,9 +291,9 @@ contract FarmLensV2 { uint256 decimals1 = IERC20(pair.token1()).safeDecimals(); if (derivedtoken0) { - return _scaleTo(reserve0, decimals1.add(18).sub(decimals0)).div(reserve1); + return reserve1 == 0 ? 0 : _scaleTo(reserve0, decimals1.add(18).sub(decimals0)).div(reserve1); } else { - return _scaleTo(reserve1, decimals0.add(18).sub(decimals1)).div(reserve0); + return reserve0 == 0 ? 0 : _scaleTo(reserve1, decimals0.add(18).sub(decimals1)).div(reserve0); } } @@ -359,7 +369,7 @@ contract FarmLensV2 { FarmInfo[] memory farmInfos = new FarmInfo[](whitelistLength); uint256 chefTotalAlloc = chef.totalAllocPoint(); - uint256 chefJoePerSec = chef.joePerSec(); + uint256 chefJoePerSec = _joePerSec(address(chef)); for (uint256 i; i < whitelistLength; i++) { uint256 pid = whitelistedPids[i]; @@ -432,7 +442,7 @@ contract FarmLensV2 { address user, uint256[] calldata whitelistedPids ) private view returns (FarmInfoBMCJ[] memory) { - GlobalInfo memory globalInfo = GlobalInfo(address(bmcj), bmcj.totalAllocPoint(), bmcj.joePerSec()); + GlobalInfo memory globalInfo = GlobalInfo(address(bmcj), bmcj.totalAllocPoint(), _joePerSec(address(bmcj))); uint256 whitelistLength = whitelistedPids.length; FarmInfoBMCJ[] memory farmInfos = new FarmInfoBMCJ[](whitelistLength); @@ -518,7 +528,7 @@ contract FarmLensV2 { poolReserveUsd / BP_PRECISION; - if (user.amount != 0 && user.factor != 0) { + if (user.amount != 0 && user.factor != 0 && pool.totalFactor != 0) { uint256 userLpUsd = user.amount.mul(farmInfo.reserveUsd) / pool.totalLpSupply; farmInfo.userBoostedApr = diff --git a/test/foundry/FarmLensV2.t.sol b/test/foundry/FarmLensV2.t.sol new file mode 100644 index 00000000..9c5a0827 --- /dev/null +++ b/test/foundry/FarmLensV2.t.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma experimental ABIEncoderV2; +pragma solidity 0.6.12; + +import "forge-std/Test.sol"; + +import "../../contracts/traderjoe/FarmLensV2.sol"; + +contract testFarmLensV2 is Test { + FarmLensV2 constant lens = FarmLensV2(0xF16d25Eba0D8E51cEAF480141bAf577aE55bfdd2); + + function setUp() public { + vm.createSelectFork(vm.rpcUrl("avalanche"), 37292546); + } + + function test_Edge() public { + vm.expectRevert("SafeMath: division by zero"); + lens.getAllFarmData(new uint256[](1), new uint256[](1), new uint256[](1), address(this)); + + FarmLensV2 newLens = new FarmLensV2( + lens.joe(), + lens.wavax(), + lens.wavaxUsdte(), + lens.wavaxUsdce(), + lens.wavaxUsdc(), + lens.joeFactory(), + lens.chefv2(), + lens.chefv3(), + lens.bmcj() + ); + + newLens.getAllFarmData(new uint256[](1), new uint256[](1), new uint256[](1), address(this)); + } +}