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

Refactor often-used modifiers into private functions to reduce interaction costs for users

Summary

There are some modifiers within the Beanstalk project that are very often used. Some examples are: mowSender(), fundsSafu(), or noSupplyChange(). There is a technique that the Beanstalk team can employ to make interactions with its contracts cheaper by embedding these modifiers in private functions. This will result in significant gas savings (up to 50%), making interactions for Beanstalk's users much more cost-effective.

Vulnerability Details

Currently, the modifiers from the Summary section are implemented as regular modifiers and used as such.

Examples:

fundsSafu() modifier:

modifier fundsSafu() {
_;
address[] memory tokens = getTokensOfInterest();
(uint256[] memory entitlements, uint256[] memory balances) = getTokenEntitlementsAndBalances(tokens);
for (uint256 i; i < tokens.length; i++) {
require(balances[i] >= entitlements[i], "INV: Insufficient token balance");
}
}

noSupplyChange modifier:

modifier noSupplyChange() {
uint256 initialSupply = C.bean().totalSupply();
_;
require(C.bean().totalSupply() == initialSupply, "INV: Supply changed");
}

Usages:

SiloFacet#deposit()

function deposit(
address token,
uint256 _amount,
LibTransfer.From mode
)
external
payable
@> fundsSafu
@> noSupplyChange
noOutFlow
nonReentrant
@> mowSender(token)
returns (uint256 amount, uint256 _bdv, int96 stem)

SiloFacet#withdrawDeposit()

function withdrawDeposit(
address token,
int96 stem,
uint256 amount,
LibTransfer.To mode
@> ) external payable fundsSafu noSupplyChange oneOutFlow(token) mowSender(token) nonReentrant {

Note that in the documentation for the fundsSafu() modifier, it is stated that it should be used on every function that can write.

/**
* @notice Ensures all user asset entitlements are coverable by contract balances.
@> * @dev Should be used on every function that can write, excepting Diamond functions.
*/
modifier fundsSafu() {

However, when using modifiers very often, as is the case with those mentioned above, it is recommended to embed these modifiers in private functions. This will make the calls where these modifiers are invoked much cheaper. By applying this change, Beanstalk can significantly reduce their gas costs.

Written PoC

I wrote this simple contract which can be copy-pasted in Remix to show the gas saved by employing this approach.

contract B {
bool public entered;
modifier enteredMod() {
entered = true;
_;
}
uint256 public sum;
// 75336 gas
function sumFunc() external enteredMod {
sum = 5 + 10;
}
modifier enteredModPrivate() {
_enteredMod();
_;
}
function _enteredMod() private {
entered = true;
}
// 32839 gas
function sumFuncWithInternalModifier() external enteredModPrivate() {
sum = 5 + 20;
}
}

As can be clearly seen, employing this approach reduces gas costs by about 2 times.

Impact

Higher gas costs for users to interact with the Beanstalk project.

Tools Used

Manual code review, Remix IDE

Recommendations

Consider consolidating the logic of often-used modifiers within a private function. For example, the modifier referenced below could be refactored as demonstrated:

modifier fundsSafu() {
_;
+ _fundsSafu();
+ }
+
+ function _fundsSafu() private {
address[] memory tokens = getTokensOfInterest();
- (
- uint256[] memory entitlements,
- uint256[] memory balances
- ) = getTokenEntitlementsAndBalances(tokens);
+ (uint256[] memory entitlements, uint256[] memory balances) = getTokenEntitlementsAndBalances(tokens);
for (uint256 i; i < tokens.length; i++) {
require(balances[i] >= entitlements[i], "INV: Insufficient token balance");
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational/Gas

Invalid as per docs https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity

Appeal created

krisp Submitter
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational/Gas

Invalid as per docs https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity

Support

FAQs

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