Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

contracts-bedrock: prevent overflows in ResourceMetering + prevent grief #5064

Merged
merged 11 commits into from
Mar 11, 2023

Conversation

tynes
Copy link
Contributor

@tynes tynes commented Mar 7, 2023

Description

When multiplying a uint64 and uint128 and assigning to a uint256, the solidity checked math applies to the types of the numbers being multiplied. This means that solidity catches an overflow when the result of larger than a uint128 even though its assigned to a uint256.
This PR uses unchecked math to prevent this kind of overflow instead of casting the values to uint256 because it is safe to use unchecked math here. The following inequality always holds true, which shows that it is safe:

type(uint64).max * type(uint128).max < type(uint256).max

Update:
The above unchecked logic was removed in favor of lowering the max deposit base fee. The values are simply type casted to uint256 when doing the math to prevent overflows instead of doing unchecked math.

Test coverage is added for max resource consumption with a max deposit base fee as well as some test coverage for invariants that must be held for the system to work properly, such as the max base fee being larger than the min base fee and the initial base fee being in between the min and the max.

The invariant must be held that the user is able to request the max amount of resources when the base fee is at its max value. If the max base fee is too large, then it will result in more L1 gas being consumed than the L1 block gas limit. Test coverage is added to ensure that the block gas limit can compute a deposit when the max base fee is set.

Update 2:
The max resource amount has been updated to 20 million with the same target resources, meaning that the base fee will ratchet up much more quickly. This keeps the gas prices the same for when we are around the target and they will increase much more aggressively when there is high usage. This will make it much more expensive to continuously frontrun a deposit and buy the max resources, causing it to revert.

The CSV file generated can be found in google sheets here

It is a known issue that the deposit base fee can rise to a point where it is impossible to buy more resources on L2. It should be an invariant that you can buy the max resources no matter what the deposit base fee is, but we cannot address that before going to mainnet. We need to eventually add an alternative deposit path where the L2 gas can be purchased by sending ether instead of with a gas burn. That is too large of a project to take on before mainnet, but that is how the invariant can be held.

The following data was taken from the csv file

prevBaseFee prevBoughtGas prevBlockNumDiff l1BaseFee requestedGas gasConsumed ethPrice usdCost success
50000000000 0 0 50000000000 20000000 20000318 $1600 $1600 success
50000000000 0 0 1000000000 100000 5000370 $1600 $8 success

The amount of gas burnt is dynamic based on the current L1 base fee to hold user fees constant. You can see that it costs $1600 when the eth price is $1600 to buy the max resource limit when the deposit base fee is 50 gwei. You can see when the L1 base fee is 1 gwei and the user requests 100000 gas, it results in 5000370 gas being used. This is a 50:1 ratio.

@tynes tynes requested a review from a team as a code owner March 7, 2023 02:14
@changeset-bot
Copy link

changeset-bot bot commented Mar 7, 2023

⚠️ No Changeset found

Latest commit: 87347d9

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@tynes tynes force-pushed the feat/prevent-overflows branch 2 times, most recently from 0ad9161 to 48d014b Compare March 8, 2023 01:24
@mergify
Copy link
Contributor

mergify bot commented Mar 8, 2023

Hey @tynes! This PR has merge conflicts. Please fix them before continuing review.

@mergify mergify bot added the conflict label Mar 8, 2023
@mergify mergify bot removed the conflict label Mar 8, 2023
@codecov
Copy link

codecov bot commented Mar 8, 2023

Codecov Report

Merging #5064 (87347d9) into develop (68c357c) will decrease coverage by 0.56%.
The diff coverage is 100.00%.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #5064      +/-   ##
===========================================
- Coverage    41.12%   40.57%   -0.56%     
===========================================
  Files          339      318      -21     
  Lines        20796    20184     -612     
  Branches       772      661     -111     
===========================================
- Hits          8553     8190     -363     
+ Misses       11586    11337     -249     
  Partials       657      657              
Flag Coverage Δ
bedrock-go-tests 36.78% <ø> (ø)
contracts-bedrock-tests 51.10% <100.00%> (+1.04%) ⬆️
contracts-tests 98.86% <ø> (ø)
core-utils-tests ?
dtl-tests 47.15% <ø> (ø)
fault-detector-tests 33.88% <ø> (ø)
sdk-tests 39.05% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
...ontracts-bedrock/contracts/L1/ResourceMetering.sol 94.44% <100.00%> (+94.44%) ⬆️

... and 21 files with indirect coverage changes

@tynes
Copy link
Contributor Author

tynes commented Mar 8, 2023

I've added an additional commit that includes a table test for testing the resource params at a bunch of different values and then it writes the output to csv. It includes the USD cost to buy up deposit gas

@tynes
Copy link
Contributor Author

tynes commented Mar 10, 2023

I'd like to rebase this on #5101 to get more accurate benchmarks

@mergify
Copy link
Contributor

mergify bot commented Mar 10, 2023

Hey @tynes! This PR has merge conflicts. Please fix them before continuing review.

@mergify mergify bot added the conflict label Mar 10, 2023
@mergify mergify bot removed the conflict label Mar 10, 2023
@tynes tynes changed the title contracts-bedrock: prevent overflows in ResourceMetering contracts-bedrock: prevent overflows in ResourceMetering + prevent grief Mar 10, 2023
@mergify
Copy link
Contributor

mergify bot commented Mar 10, 2023

Hey @tynes! This PR has merge conflicts. Please fix them before continuing review.

@mergify mergify bot added the conflict label Mar 10, 2023
When multiplying a uint64 and uint128 and assigning to
a uint256, the solidity checked math applies to the
types of the numbers being multiplied. This means that
solidity catches an overflow when the result of larger than
a uint128 even though its assigned to a uint256.
This PR uses unchecked math to prevent this kind of overflow
instead of casting the values to uint256 because it is
safe to use unchecked math here. The following inequality
always holds true, which shows that it is safe:

``` solidity
type(uint64).max * type(uint128).max < type(uint256).max
```
Remove the unchecked arithmetic in favor of lowering the
max base fee. This will prevent situations in which the
max base fee causes gas consumption greater than the
block gas limit.
@mergify mergify bot removed the conflict label Mar 10, 2023
Copy link
Contributor

@smartcontracts smartcontracts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm minus comments

Copy link
Member

@clabby clabby left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tynes tynes merged commit 35d4a37 into develop Mar 11, 2023
@tynes tynes deleted the feat/prevent-overflows branch March 11, 2023 03:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants