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

If `s.sys.shipmentRoutes` is set to 0, ```LibShipping::ship()``` emits a wrong event

Summary

The LibShipping::ship() function is public, allowing any user to initiate the distribution process of BEAN across predefined shipment routes. However, if all shipment routes are configured with zero points (for example: for pausing the distribution of resources, emergency brake, strategic planning etc.), indicating no distribution should occur, the function still emits a Shipped event with the total number of Beans intended for distribution (beansToShip). This behavior lead to misinformation among users and external systems monitoring the contract's events, as it falsely suggests that a distribution of BEAN has occurred.

Vulnerability Details

The core of the vulnerability lies in the ship function's logic, specifically in the unconditional emission of the Shipped event at the end of its execution. Despite the function correctly handling the scenario where all shipment routes have zero points (thus not distributing any Beans), it does not differentiate this case when emitting the Shipped event. As a result, the event is emitted with the full amount of BEAN that were supposed to be shipped, even though no actual distribution took place.

library LibShipping {
/**
* @notice Emitted during Sunrise when Beans mints are shipped through active routes.
* @param season The Season in which Beans were distributed.
* @param shipmentAmount The amount of Beans across all routes.
*/
event Shipped(uint32 indexed season, uint256 shipmentAmount);
/**
* @notice Distributes Beans across all active shipping routes.
* @param beansToShip The total number of Beans to distribute.
*/
function ship(uint256 beansToShip) public {
AppStorage storage s = LibAppStorage.diamondStorage();
uint256 remainingBeansToShip = beansToShip;
@> ShipmentRoute[] memory shipmentRoutes = s.sys.shipmentRoutes;
ShipmentPlan[] memory shipmentPlans = new ShipmentPlan[](shipmentRoutes.length);
uint256[] memory shipmentAmounts = new uint256[](shipmentRoutes.length);
uint256 totalPoints;
(shipmentPlans, totalPoints) = getShipmentPlans(shipmentRoutes);
// May need to calculate individual stream rewards multiple times, since
// they are dependent on each others caps. Once a cap is reached, excess Beans are
// spread to other streams, proportional to their points.
for (uint256 i; i < shipmentRoutes.length; i++) {
bool capExceeded;
// Calculate the amount of rewards to each stream. Ignores cap and plans with 0 points.
getBeansFromPoints(
shipmentAmounts,
shipmentPlans,
totalPoints,
remainingBeansToShip
);
// Iterate though each stream, checking if cap is exceeded.
for (uint256 j; j < shipmentAmounts.length; j++) {
// If shipment amount exceeds plan cap, adjust plan and totals before recomputing.
if (shipmentAmounts[j] > shipmentPlans[j].cap) {
shipmentAmounts[j] = shipmentPlans[j].cap;
remainingBeansToShip -= shipmentPlans[j].cap;
totalPoints -= shipmentPlans[j].points;
shipmentPlans[j].points = 0;
capExceeded = true;
}
}
// If no cap exceeded, amounts are final.
if (!capExceeded) break;
}
// Ship it.
for (uint256 i; i < shipmentAmounts.length; i++) {
if (shipmentAmounts[i] == 0) continue;
LibReceiving.receiveShipment(
shipmentRoutes[i].recipient,
shipmentAmounts[i],
shipmentRoutes[i].data
);
}
@> emit Shipped(s.sys.season.current, beansToShip);
}

Impact

Users who monitor the Shipped event to keep track of BEAN distributions might be deceived into thinking that a distribution has taken place when, in reality, no BEAN have been distributed. This misunderstanding becomes particularly problematic considering that the Beanstalk system enables users to delegate actions to others based on specific scenarios through the use of the Tractor. Consequently, the inaccurate emission of events can trigger erroneous delegated actions.

Tools Used

Manual review

Recommendations

Modify the ship function to include a condition for emitting the Shipped event ensuring that the event is only emitted if at least one shipment route results in an actual distribution of BEAN.

Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

If `s.sys.shipmentRoutes` is set to 0, ```LibShipping::ship()``` emits a wrong event

Appeal created

kiteweb3 Submitter
12 months ago
kiteweb3 Submitter
12 months ago
inallhonesty Lead Judge
12 months ago
inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

If `s.sys.shipmentRoutes` is set to 0, ```LibShipping::ship()``` emits a wrong event

Support

FAQs

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