DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: low
Invalid

Reentrancy vulnerabilities found in multiple function calls

Summary

Detection of the reentrancy bug found in multiple functions.

Vulnerability Details

Reentrancy in Fertilizer._beforeTokenTransfer(address,address,address,uint256[],uint256[],bytes) (contracts/tokens/Fertilizer/Fertilizer.sol#62-73):
External calls:
- _update(from,ids,bpf) (contracts/tokens/Fertilizer/Fertilizer.sol#71)
- IBS(owner()).payFertilizer(account,amount) (contracts/tokens/Fertilizer/Fertilizer.sol#77)
- _update(to,ids,bpf) (contracts/tokens/Fertilizer/Fertilizer.sol#72)
- IBS(owner()).payFertilizer(account,amount) (contracts/tokens/Fertilizer/Fertilizer.sol#77)
State variables written after the call(s):
- _update(to,ids,bpf) (contracts/tokens/Fertilizer/Fertilizer.sol#72)
- _balances[ids[i]][account].lastBpf = uint128(stopBpf) (contracts/tokens/Fertilizer/Fertilizer.sol#90)
Internalizer._balances (contracts/tokens/Fertilizer/Internalizer.sol#31) can be used in cross function reentrancies:
- Fertilizer.__update(address,uint256[],uint256) (contracts/tokens/Fertilizer/Fertilizer.sol#80-94)
- Internalizer._transfer(address,address,uint256,uint256) (contracts/tokens/Fertilizer/Internalizer.sol#71-85)
- Internalizer.balanceOf(address,uint256) (contracts/tokens/Fertilizer/Internalizer.sol#51-54)
- Fertilizer.balanceOfFertilized(address,uint256[]) (contracts/tokens/Fertilizer/Fertilizer.sol#96-106)
- Fertilizer.balanceOfUnfertilized(address,uint256[]) (contracts/tokens/Fertilizer/Fertilizer.sol#108-117)
- Fertilizer.beanstalkMint(address,uint256,uint128,uint128) (contracts/tokens/Fertilizer/Fertilizer.sol#47-60)
- Internalizer.lastBalanceOf(address,uint256) (contracts/tokens/Fertilizer/Internalizer.sol#56-59)
Reentrancy in Order._cancelPodOrder(Order.PodOrder,LibTransfer.To) (contracts/beanstalk/market/MarketplaceFacet/Order.sol#134-140):
External calls:
- LibTransfer.sendToken(C.bean(),amountBeans,podOrder.orderer,mode) (contracts/beanstalk/market/MarketplaceFacet/Order.sol#137)
State variables written after the call(s):
- delete s.sys.podOrders[id] (contracts/beanstalk/market/MarketplaceFacet/Order.sol#138)
ReentrancyGuard.s (contracts/beanstalk/ReentrancyGuard.sol#16) can be used in cross function reentrancies:
- PodTransfer.allowancePods(address,address,uint256) (contracts/beanstalk/market/MarketplaceFacet/PodTransfer.sol#35-41)
Reentrancy in ClaimFacet._claimPlenty(address,address,LibTransfer.To) (contracts/beanstalk/silo/SiloFacet/ClaimFacet.sol#95-108):
External calls:
- LibTransfer.sendToken(sopToken,plenty,LibTractor._user(),toMode) (contracts/beanstalk/silo/SiloFacet/ClaimFacet.sol#100)
State variables written after the call(s):
- s.accts[account].sop.perWellPlenty[well].plenty = 0 (contracts/beanstalk/silo/SiloFacet/ClaimFacet.sol#101)
ReentrancyGuard.s (contracts/beanstalk/ReentrancyGuard.sol#16) can be used in cross function reentrancies:
- ClaimFacet._plant(address) (contracts/beanstalk/silo/SiloFacet/ClaimFacet.sol#168-205)
- s.sys.sop.plentyPerSopToken[address(sopToken)] -= plenty (contracts/beanstalk/silo/SiloFacet/ClaimFacet.sol#104)
ReentrancyGuard.s (contracts/beanstalk/ReentrancyGuard.sol#16) can be used in cross function reentrancies:
- ClaimFacet._plant(address) (contracts/beanstalk/silo/SiloFacet/ClaimFacet.sol#168-205)
Reentrancy in Order._fillPodOrder(Order.PodOrder,address,uint256,uint256,uint256,LibTransfer.To) (contracts/beanstalk/market/MarketplaceFacet/Order.sol#79-129):
External calls:
- LibTransfer.sendToken(C.bean(),costInBeans,filler,mode) (contracts/beanstalk/market/MarketplaceFacet/Order.sol#107)
State variables written after the call(s):
- _transferPlot(filler,podOrder.orderer,podOrder.fieldId,index,start,podAmount) (contracts/beanstalk/market/MarketplaceFacet/Order.sol#113)
- s.accts[account].fields[fieldId].plots[index] = amount (contracts/beanstalk/market/MarketplaceFacet/PodTransfer.sol#62)
- s.accts[account].fields[fieldId].plotIndexes.push(index) (contracts/beanstalk/market/MarketplaceFacet/PodTransfer.sol#63)
- s.accts[account].fields[fieldId].plots[index] = start (contracts/beanstalk/market/MarketplaceFacet/PodTransfer.sol#76)
- delete s.accts[account].fields[fieldId].plots[index] (contracts/beanstalk/market/MarketplaceFacet/PodTransfer.sol#78)
- s.accts[account].fields[fieldId].plots[newIndex] = amountAfterEnd (contracts/beanstalk/market/MarketplaceFacet/PodTransfer.sol#84)
- s.accts[account].fields[fieldId].plotIndexes.push(newIndex) (contracts/beanstalk/market/MarketplaceFacet/PodTransfer.sol#85)
ReentrancyGuard.s (contracts/beanstalk/ReentrancyGuard.sol#16) can be used in cross function reentrancies:
- PodTransfer.allowancePods(address,address,uint256) (contracts/beanstalk/market/MarketplaceFacet/PodTransfer.sol#35-41)
- delete s.sys.podOrders[id] (contracts/beanstalk/market/MarketplaceFacet/Order.sol#116)
ReentrancyGuard.s (contracts/beanstalk/ReentrancyGuard.sol#16) can be used in cross function reentrancies:
- PodTransfer.allowancePods(address,address,uint256) (contracts/beanstalk/market/MarketplaceFacet/PodTransfer.sol#35-41)
Reentrancy in Fertilizer.beanstalkMint(address,uint256,uint128,uint128) (contracts/tokens/Fertilizer/Fertilizer.sol#47-60):
External calls:
- _update(account,ids,bpf) (contracts/tokens/Fertilizer/Fertilizer.sol#56)
- IBS(owner()).payFertilizer(account,amount) (contracts/tokens/Fertilizer/Fertilizer.sol#77)
State variables written after the call(s):
- _balances[id][account].lastBpf = bpf (contracts/tokens/Fertilizer/Fertilizer.sol#58)
Internalizer._balances (contracts/tokens/Fertilizer/Internalizer.sol#31) can be used in cross function reentrancies:
- Fertilizer.__update(address,uint256[],uint256) (contracts/tokens/Fertilizer/Fertilizer.sol#80-94)
- Internalizer._transfer(address,address,uint256,uint256) (contracts/tokens/Fertilizer/Internalizer.sol#71-85)
- Internalizer.balanceOf(address,uint256) (contracts/tokens/Fertilizer/Internalizer.sol#51-54)
- Fertilizer.balanceOfFertilized(address,uint256[]) (contracts/tokens/Fertilizer/Fertilizer.sol#96-106)
- Fertilizer.balanceOfUnfertilized(address,uint256[]) (contracts/tokens/Fertilizer/Fertilizer.sol#108-117)
- Fertilizer.beanstalkMint(address,uint256,uint128,uint128) (contracts/tokens/Fertilizer/Fertilizer.sol#47-60)
- Internalizer.lastBalanceOf(address,uint256) (contracts/tokens/Fertilizer/Internalizer.sol#56-59)
Reentrancy in Fertilizer.beanstalkMint(address,uint256,uint128,uint128) (contracts/tokens/Fertilizer/Fertilizer.sol#47-60):
External calls:
- _update(account,ids,bpf) (contracts/tokens/Fertilizer/Fertilizer.sol#56)
- IBS(owner()).payFertilizer(account,amount) (contracts/tokens/Fertilizer/Fertilizer.sol#77)
- _safeMint(account,id,amount,bytes(0)) (contracts/tokens/Fertilizer/Fertilizer.sol#59)
- response = IERC1155Receiver(to).onERC1155Received(operator,from,id,amount,data) (contracts/tokens/Fertilizer/Fertilizer1155.sol#104-114)
State variables written after the call(s):
- _safeMint(account,id,amount,bytes(0)) (contracts/tokens/Fertilizer/Fertilizer.sol#59)
- _balances[id][from].amount = fromBalance - _amount (contracts/tokens/Fertilizer/Internalizer.sol#82)
- _balances[id][to].amount = _balances[id][to].amount.add(_amount) (contracts/tokens/Fertilizer/Internalizer.sol#84)
Internalizer._balances (contracts/tokens/Fertilizer/Internalizer.sol#31) can be used in cross function reentrancies:
- Fertilizer.__update(address,uint256[],uint256) (contracts/tokens/Fertilizer/Fertilizer.sol#80-94)
- Internalizer._transfer(address,address,uint256,uint256) (contracts/tokens/Fertilizer/Internalizer.sol#71-85)
- Internalizer.balanceOf(address,uint256) (contracts/tokens/Fertilizer/Internalizer.sol#51-54)
- Fertilizer.balanceOfFertilized(address,uint256[]) (contracts/tokens/Fertilizer/Fertilizer.sol#96-106)
- Fertilizer.balanceOfUnfertilized(address,uint256[]) (contracts/tokens/Fertilizer/Fertilizer.sol#108-117)
- Fertilizer.beanstalkMint(address,uint256,uint128,uint128) (contracts/tokens/Fertilizer/Fertilizer.sol#47-60)
- Internalizer.lastBalanceOf(address,uint256) (contracts/tokens/Fertilizer/Internalizer.sol#56-59)
Reentrancy in FertilizerFacet.claimFertilized(uint256[],LibTransfer.To) (contracts/beanstalk/barn/FertilizerFacet.sol#47-54):
External calls:
- amount = C.fertilizer().beanstalkUpdate(LibTractor._user(),ids,s.sys.fert.bpf) (contracts/beanstalk/barn/FertilizerFacet.sol#51)
State variables written after the call(s):
- s.sys.fert.fertilizedPaidIndex += amount (contracts/beanstalk/barn/FertilizerFacet.sol#52)
FertilizerFacet.s (contracts/beanstalk/barn/FertilizerFacet.sol#35) can be used in cross function reentrancies:
- FertilizerFacet.beansPerFertilizer() (contracts/beanstalk/barn/FertilizerFacet.sol#164-166)
- FertilizerFacet.claimFertilized(uint256[],LibTransfer.To) (contracts/beanstalk/barn/FertilizerFacet.sol#47-54)
- FertilizerFacet.getActiveFertilizer() (contracts/beanstalk/barn/FertilizerFacet.sol#156-158)
- FertilizerFacet.getCurrentHumidity() (contracts/beanstalk/barn/FertilizerFacet.sol#172-174)
- FertilizerFacet.getEndBpf() (contracts/beanstalk/barn/FertilizerFacet.sol#176-178)
- FertilizerFacet.getFertilizer(uint128) (contracts/beanstalk/barn/FertilizerFacet.sol#140-142)
- FertilizerFacet.getFertilizers() (contracts/beanstalk/barn/FertilizerFacet.sol#212-228)
- FertilizerFacet.getFirst() (contracts/beanstalk/barn/FertilizerFacet.sol#148-150)
- FertilizerFacet.getLast() (contracts/beanstalk/barn/FertilizerFacet.sol#152-154)
- FertilizerFacet.isFertilizing() (contracts/beanstalk/barn/FertilizerFacet.sol#160-162)
- FertilizerFacet.leftoverBeans() (contracts/beanstalk/barn/FertilizerFacet.sol#136-138)
- FertilizerFacet.mintFertilizer(uint256,uint256,uint256) (contracts/beanstalk/barn/FertilizerFacet.sol#63-91)
- FertilizerFacet.payFertilizer(address,uint256) (contracts/beanstalk/barn/FertilizerFacet.sol#96-103)
- FertilizerFacet.totalFertilizedBeans() (contracts/beanstalk/barn/FertilizerFacet.sol#124-126)
- FertilizerFacet.totalFertilizerBeans() (contracts/beanstalk/barn/FertilizerFacet.sol#132-134)
- FertilizerFacet.totalUnfertilizedBeans() (contracts/beanstalk/barn/FertilizerFacet.sol#128-130)
Reentrancy in SeasonFacet.gm(address,LibTransfer.To) (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#48-62):
External calls:
- caseId = calcCaseIdandUpdate(deltaB) (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#56)
- C.bean().mint(address(this),sopBeans) (contracts/libraries/Silo/LibFlood.sol#295)
- C.bean().approve(wellDeltaB.well,sopBeans) (contracts/libraries/Silo/LibFlood.sol#298)
- amountOut = IWell(wellDeltaB.well).swapFrom(C.bean(),sopToken,sopBeans,0,address(this),type()(uint256).max) (contracts/libraries/Silo/LibFlood.sol#299-306)
- LibFlood.handleRain(caseId) (contracts/beanstalk/sun/SeasonFacet/Weather.sol#97)
- stepSun(deltaB,caseId) (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#59)
- C.bean().mint(address(this),uint256(deltaB)) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#46)
State variables written after the call(s):
- stepSun(deltaB,caseId) (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#59)
- s.sys.soil = amount.toUint128() (contracts/beanstalk/sun/SeasonFacet/Sun.sol#82)
- s.sys.season.abovePeg = true (contracts/beanstalk/sun/SeasonFacet/Sun.sol#50)
- s.sys.season.abovePeg = false (contracts/beanstalk/sun/SeasonFacet/Sun.sol#55)
ReentrancyGuard.s (contracts/beanstalk/ReentrancyGuard.sol#16) can be used in cross function reentrancies:
- Weather.calcCaseIdandUpdate(int256) (contracts/beanstalk/sun/SeasonFacet/Weather.sol#87-99)
- Distribution.getShipmentRoutes() (contracts/beanstalk/sun/SeasonFacet/Distribution.sol#32-34)
- SeasonFacet.gm(address,LibTransfer.To) (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#48-62)
- SeasonFacet.incentivize(address,LibTransfer.To) (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#92-110)
- SeasonFacet.seasonTime() (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#68-72)
- Distribution.setShipmentRoutes(ShipmentRoute[]) (contracts/beanstalk/sun/SeasonFacet/Distribution.sol#40-47)
- Sun.setSoil(uint256) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#81-84)
- Sun.setSoilAbovePeg(uint256,uint256) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#71-79)
- Oracle.stepOracle() (contracts/beanstalk/sun/SeasonFacet/Oracle.sol#21-27)
- SeasonFacet.stepSeason() (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#79-84)
- Sun.stepSun(int256,uint256) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#41-57)
- Weather.updateBeanToMaxLPRatio(int80,uint256) (contracts/beanstalk/sun/SeasonFacet/Weather.sol#149-178)
- Weather.updateTemperature(int8,uint256) (contracts/beanstalk/sun/SeasonFacet/Weather.sol#126-143)
Reentrancy in ReseedBarn.init(ReseedBarn.Fertilizers[],uint256,uint256,uint256,uint128) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#47-70):
External calls:
- fertilizerProxy = new TransparentUpgradeableProxy(address(fertilizer),address(this),abi.encode(IFertilizer.init.selector)) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#58-62)
- mintFertilizers(Fertilizer(address(fertilizerProxy)),fertilizerIds) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#64)
- fertilizerProxy.beanstalkMint(f.accountData[j].account,fid,f.accountData[j].amount,f.accountData[j].lastBpf) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#88-93)
State variables written after the call(s):
- s.sys.season.fertilizing = true (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#65)
ReseedBarn.s (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#41) can be used in cross function reentrancies:
- ReseedBarn.init(ReseedBarn.Fertilizers[],uint256,uint256,uint256,uint128) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#47-70)
- ReseedBarn.mintFertilizers(Fertilizer,ReseedBarn.Fertilizers[]) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#72-96)
- s.sys.fert.activeFertilizer = activeFertilizer (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#66)
ReseedBarn.s (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#41) can be used in cross function reentrancies:
- ReseedBarn.init(ReseedBarn.Fertilizers[],uint256,uint256,uint256,uint128) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#47-70)
- ReseedBarn.mintFertilizers(Fertilizer,ReseedBarn.Fertilizers[]) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#72-96)
- s.sys.fert.fertilizedIndex = fertilizedIndex (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#67)
ReseedBarn.s (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#41) can be used in cross function reentrancies:
- ReseedBarn.init(ReseedBarn.Fertilizers[],uint256,uint256,uint256,uint128) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#47-70)
- ReseedBarn.mintFertilizers(Fertilizer,ReseedBarn.Fertilizers[]) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#72-96)
- s.sys.fert.unfertilizedIndex = unfertilizedIndex (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#68)
ReseedBarn.s (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#41) can be used in cross function reentrancies:
- ReseedBarn.init(ReseedBarn.Fertilizers[],uint256,uint256,uint256,uint128) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#47-70)
- ReseedBarn.mintFertilizers(Fertilizer,ReseedBarn.Fertilizers[]) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#72-96)
- s.sys.fert.bpf = bpf (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#69)
ReseedBarn.s (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#41) can be used in cross function reentrancies:
- ReseedBarn.init(ReseedBarn.Fertilizers[],uint256,uint256,uint256,uint128) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#47-70)
- ReseedBarn.mintFertilizers(Fertilizer,ReseedBarn.Fertilizers[]) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#72-96)
Reentrancy in ReseedBarn.mintFertilizers(Fertilizer,ReseedBarn.Fertilizers[]) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#72-96):
External calls:
- fertilizerProxy.beanstalkMint(f.accountData[j].account,fid,f.accountData[j].amount,f.accountData[j].lastBpf) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#88-93)
State variables written after the call(s):
- s.sys.fert.fertFirst = fid (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#80)
ReseedBarn.s (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#41) can be used in cross function reentrancies:
- ReseedBarn.init(ReseedBarn.Fertilizers[],uint256,uint256,uint256,uint128) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#47-70)
- ReseedBarn.mintFertilizers(Fertilizer,ReseedBarn.Fertilizers[]) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#72-96)
- s.sys.fert.nextFid[fertilizerIds[i - 1].fertilizerId] = fid (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#81)
ReseedBarn.s (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#41) can be used in cross function reentrancies:
- ReseedBarn.init(ReseedBarn.Fertilizers[],uint256,uint256,uint256,uint128) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#47-70)
- ReseedBarn.mintFertilizers(Fertilizer,ReseedBarn.Fertilizers[]) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#72-96)
- s.sys.fert.fertLast = fid (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#82)
ReseedBarn.s (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#41) can be used in cross function reentrancies:
- ReseedBarn.init(ReseedBarn.Fertilizers[],uint256,uint256,uint256,uint128) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#47-70)
- ReseedBarn.mintFertilizers(Fertilizer,ReseedBarn.Fertilizers[]) (contracts/beanstalk/init/reseed/L2/ReseedBarn.sol#72-96)
Reentrancy in Sun.stepSun(int256,uint256) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#41-57):
External calls:
- C.bean().mint(address(this),uint256(deltaB)) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#46)
State variables written after the call(s):
- setSoilAbovePeg(s.sys.fields[s.sys.activeField].harvestable - priorHarvestable,caseId) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#49)
- s.sys.soil = amount.toUint128() (contracts/beanstalk/sun/SeasonFacet/Sun.sol#82)
ReentrancyGuard.s (contracts/beanstalk/ReentrancyGuard.sol#16) can be used in cross function reentrancies:
- Distribution.getShipmentRoutes() (contracts/beanstalk/sun/SeasonFacet/Distribution.sol#32-34)
- Distribution.setShipmentRoutes(ShipmentRoute[]) (contracts/beanstalk/sun/SeasonFacet/Distribution.sol#40-47)
- s.sys.season.abovePeg = true (contracts/beanstalk/sun/SeasonFacet/Sun.sol#50)
ReentrancyGuard.s (contracts/beanstalk/ReentrancyGuard.sol#16) can be used in cross function reentrancies:
- Distribution.getShipmentRoutes() (contracts/beanstalk/sun/SeasonFacet/Distribution.sol#32-34)
- Distribution.setShipmentRoutes(ShipmentRoute[]) (contracts/beanstalk/sun/SeasonFacet/Distribution.sol#40-47)

Impact

An attacker can manipulate the calls to extract funds without authorization.

Tools Used

Slither

Recommendations

Apply the check-effects-interactions pattern.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Lack of quality
Assigned finding tags:

Quality

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.