From 405de7984241eeafe00441272ca629039e5f992e Mon Sep 17 00:00:00 2001 From: Louis <107303182+0x0Louis@users.noreply.github.com> Date: Fri, 3 Nov 2023 18:37:35 +0100 Subject: [PATCH] Fix BMCJ div by zero error (#121) * fix bmcj div by zero * Fix code style issues with Prettier --------- Co-authored-by: Lint Action --- contracts/BoostedMasterChefJoe.sol | 20 ++++++++++++--- test/foundry/UpgradeBMCJ.t.sol | 41 ++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 test/foundry/UpgradeBMCJ.t.sol diff --git a/contracts/BoostedMasterChefJoe.sol b/contracts/BoostedMasterChefJoe.sol index 36517a10..6bb25299 100644 --- a/contracts/BoostedMasterChefJoe.sol +++ b/contracts/BoostedMasterChefJoe.sol @@ -364,12 +364,15 @@ contract BoostedMasterChefJoe is Initializable, OwnableUpgradeable, ReentrancyGu /// @notice Calculates and returns the `amount` of JOE per second /// @return amount The amount of JOE emitted per second function joePerSec() public view returns (uint256 amount) { + uint256 mcv2TotalAllocPoint = MASTER_CHEF_V2.totalAllocPoint(); + if (mcv2TotalAllocPoint == 0) return 0; + uint256 total = 1000; uint256 lpPercent = total.sub(MASTER_CHEF_V2.devPercent()).sub(MASTER_CHEF_V2.treasuryPercent()).sub( MASTER_CHEF_V2.investorPercent() ); uint256 lpShare = MASTER_CHEF_V2.joePerSec().mul(lpPercent).div(total); - amount = lpShare.mul(MASTER_CHEF_V2.poolInfo(MASTER_PID).allocPoint).div(MASTER_CHEF_V2.totalAllocPoint()); + amount = lpShare.mul(MASTER_CHEF_V2.poolInfo(MASTER_PID).allocPoint).div(mcv2TotalAllocPoint); } /// @notice View function to see pending JOE on frontend @@ -396,7 +399,12 @@ contract BoostedMasterChefJoe is Initializable, OwnableUpgradeable, ReentrancyGu if (block.timestamp > pool.lastRewardTimestamp && pool.totalLpSupply != 0 && pool.allocPoint != 0) { uint256 secondsElapsed = block.timestamp - pool.lastRewardTimestamp; - uint256 joeReward = secondsElapsed.mul(joePerSec()).mul(pool.allocPoint).div(totalAllocPoint); + + uint256 totalAllocPoint_ = totalAllocPoint; + uint256 joeReward = totalAllocPoint_ > 0 + ? secondsElapsed.mul(joePerSec()).mul(pool.allocPoint).div(totalAllocPoint_) + : 0; + accJoePerShare = accJoePerShare.add( joeReward.mul(ACC_TOKEN_PRECISION).mul(10_000 - pool.veJoeShareBp).div(pool.totalLpSupply.mul(10_000)) ); @@ -449,7 +457,11 @@ contract BoostedMasterChefJoe is Initializable, OwnableUpgradeable, ReentrancyGu uint256 veJoeShareBp = pool.veJoeShareBp; uint256 totalFactor = pool.totalFactor; - uint256 joeReward = secondsElapsed.mul(joePerSec()).mul(allocPoint).div(totalAllocPoint); + uint256 totalAllocPoint_ = totalAllocPoint; + uint256 joeReward = totalAllocPoint_ > 0 + ? secondsElapsed.mul(joePerSec()).mul(allocPoint).div(totalAllocPoint_) + : 0; + pool.accJoePerShare = pool.accJoePerShare.add( joeReward.mul(ACC_TOKEN_PRECISION).mul(10_000 - veJoeShareBp).div(lpSupply.mul(10_000)) ); @@ -473,7 +485,7 @@ contract BoostedMasterChefJoe is Initializable, OwnableUpgradeable, ReentrancyGu /// @notice Harvests JOE from `MASTER_CHEF_V2` MCJV2 and pool `MASTER_PID` to this BMCJ contract function harvestFromMasterChef() public { - MASTER_CHEF_V2.deposit(MASTER_PID, 0); + // MASTER_CHEF_V2.deposit(MASTER_PID, 0); } /// @notice Return an user's factor diff --git a/test/foundry/UpgradeBMCJ.t.sol b/test/foundry/UpgradeBMCJ.t.sol new file mode 100644 index 00000000..5d70a33d --- /dev/null +++ b/test/foundry/UpgradeBMCJ.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma experimental ABIEncoderV2; +pragma solidity 0.6.12; + +import "forge-std/Test.sol"; + +import "@openzeppelin/contracts/proxy/ProxyAdmin.sol"; +import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol"; + +import "../../contracts/BoostedMasterChefJoe.sol"; + +contract TestUpgradeBMCJ is Test { + ProxyAdmin proxyAdmin = ProxyAdmin(0x246ABeC8f8a542E892934232DB3Fd97A61E3193c); + BoostedMasterChefJoe proxy = BoostedMasterChefJoe(0x4483f0b6e2F5486D06958C20f8C39A7aBe87bf8F); + + address ms = 0x2fbB61a10B96254900C03F1644E9e1d2f5E76DD2; + + function setUp() public { + vm.createSelectFork(vm.rpcUrl("avalanche"), 37289196); + } + + function test_Upgrade() public { + uint256 previousTotalAllocPoint = proxy.totalAllocPoint(); + + vm.expectRevert("SafeMath: division by zero"); + proxy.massUpdatePools(); + + vm.expectRevert("SafeMath: division by zero"); + proxy.joePerSec(); + + address newImpl = address(new BoostedMasterChefJoe()); + + vm.prank(ms); + proxyAdmin.upgrade(TransparentUpgradeableProxy(payable(address(proxy))), newImpl); + + assertEq(proxy.joePerSec(), 0); + assertEq(proxy.totalAllocPoint(), previousTotalAllocPoint); + + proxy.massUpdatePools(); + } +}