Fix repayment field gas limit issue by splitting large plot accounts#177
Fix repayment field gas limit issue by splitting large plot accounts#177pocikerim wants to merge 4 commits intofrijo/release/PI-15from
Conversation
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
fr1jo
left a comment
There was a problem hiding this comment.
just one minor feedback, but generally this all looks good!
| } = require("../../utils/read.js"); | ||
|
|
||
| // EIP-7987 tx gas limit is 16,777,216 (2^24) | ||
| // ~70,600 gas per plot, with 95% safety margin: floor(16,777,216 * 0.95 / 70,600) = 225 |
There was a problem hiding this comment.
can we have a higher safety margin? instead of a 5% safety factor, lets do something like 30%-40% imo
| s.accts[account].fields[REPAYMENT_FIELD_ID].plotIndexes.push(podIndex); | ||
| s.accts[account].fields[REPAYMENT_FIELD_ID].piIndex[podIndex] = j; | ||
| s.accts[account].fields[REPAYMENT_FIELD_ID].piIndex[podIndex] = | ||
| s.accts[account].fields[REPAYMENT_FIELD_ID].plotIndexes.length - |
There was a problem hiding this comment.
i see you updated the function to be able to be used for accounts that have multiple plots. good job investigating.
can you update this though to cache s.accts[account].fields[REPAYMENT_FIELD_ID].plotIndexes.length? this adds 2100 gas and is unnecessary if we structure this properly
AppStorage storage s = LibAppStorage.diamondStorage();
for (uint i; i < accountPlots.length; i++) {
// cache the account and length of the plot indexes array
address account = accountPlots[i].account;
uint256 len = s.accts[account].fields[REPAYMENT_FIELD_ID].plotIndexes.length;
for (uint j; j < accountPlots[i].plots.length; j++) {
uint256 podIndex = accountPlots[i].plots[j].podIndex;
uint256 podAmount = accountPlots[i].plots[j].podAmounts;
s.accts[account].fields[REPAYMENT_FIELD_ID].plots[podIndex] = podAmount;
s.accts[account].fields[REPAYMENT_FIELD_ID].plotIndexes.push(podIndex);
s.accts[account].fields[REPAYMENT_FIELD_ID].piIndex[podIndex] = len + j;
emit RepaymentPlotAdded(account, podIndex, podAmount);
}
}
should work.
| * @notice Mirrors TempRepaymentFieldFacet for gas estimation in batch simulations | ||
| * @dev Includes ReentrancyGuard and require check to match real contract gas usage | ||
| */ | ||
| contract MockTempRepaymentFieldFacet { |
There was a problem hiding this comment.
is MockTempRepaymentFieldFacet just used to simulate data in scripts/beanstalkShipments/simulateProductionBatches.js?
if so, 1) if the contents is the mock is the same, you can just deploy TempRepaymentFieldFacet.sol and execute the functions directly ( no diamond needed).
| } = require("../../utils/read.js"); | ||
|
|
||
| // EIP-7987 tx gas limit is 16,777,216 (2^24) | ||
| // ~70,600 gas per plot, with 95% safety margin: floor(16,777,216 * 0.95 / 70,600) = 225 |
There was a problem hiding this comment.
did we get 70,600 gas via the script test? if so, we should include a 2600 gas overhead. In practice, the diamond standard (and proxies in general) have a 2600 gas overhead as a delegatecall has a gas cost to invoke logic from other contracts.
There was a problem hiding this comment.
Yes, it's a value from the test output. In the latest batch logic (ca816a8), the minimum number of plots per transaction is 15 (u can see it with running simulateProductionBatches.js). In this case, if I'm not mistaken, the gas overhead per plot would be around 173. I already set the values approximately and didn't account for it since there's a safety margin. But the result from the tests (the average varies depending on the plot count naturally it's higher when there are fewer plots) is around 70-71k.
| @@ -0,0 +1,186 @@ | |||
| const fs = require("fs"); | |||
…afety margin to 35%
Summary
Fix gas limit issue in repayment field initialization by splitting accounts with large plot counts across multiple transactions.
Problem
Accounts with ~240+ plots exceed the EIP-7987 transaction gas limit (16,777,216 gas). Each plot costs ~70,600 gas, so accounts exceeding this threshold cause transaction failures.
Affected accounts:
populateBeanstalkFieldexecutionChanges
1.
contracts/beanstalk/tempFacets/TempRepaymentFieldFacet.solFixed
piIndexmapping to correctly track plot positions when an account receives plots across multiple transactions.Why: The loop index j resets to 0 for each transaction. Using plotIndexes.length - 1 gives the actual array position.
2. utils/read.js
Added
splitWhaleAccounts()function to split accounts exceeding 200 plots into multiple entries.Why: 200 plots ≈ 14M gas, safely under the 16.7M limit with margin.
3. scripts/beanstalkShipments/populateBeanstalkField.js
Integrated whale splitting before chunking.