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

feat(entropy): Add on-chain gas limits and mark out-of-gas failures on-chain #2559

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

jayantk
Copy link
Contributor

@jayantk jayantk commented Apr 4, 2025

Summary

Follow up to the last PR around allowing providers to mark on-chain callbacks as failed. The previous PR covers cases where the contract manually reverts. This PR covers the case where the callback runs out of gas.

This PR gives each callback a gas limit which is stored in the on-chain struct. Providers can set a default gas limit, or users can manually specify a different gas limit when making a request. We mark callbacks as failed if they revert with an out-of-gas error and the transaction had enough gas to forward -- there are some EVM nuances here that we need to be careful about. See inline comments for details.

Rationale

Explicitly marking on-chain requests as failed will make the state transitions of entropy much clearer to end users.

How has this been tested?

  • Current tests cover my changes
  • Added new tests
  • Manually tested the code

Copy link

vercel bot commented Apr 4, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

6 Skipped Deployments
Name Status Preview Comments Updated (UTC)
api-reference ⬜️ Ignored (Inspect) Visit Preview Apr 4, 2025 5:28pm
component-library ⬜️ Ignored (Inspect) Visit Preview Apr 4, 2025 5:28pm
entropy-debugger ⬜️ Ignored (Inspect) Visit Preview Apr 4, 2025 5:28pm
insights ⬜️ Ignored (Inspect) Visit Preview Apr 4, 2025 5:28pm
proposals ⬜️ Ignored (Inspect) Visit Preview Apr 4, 2025 5:28pm
staking ⬜️ Ignored (Inspect) Visit Preview Apr 4, 2025 5:28pm


function testRequestWithRevertingCallback() public {
uint32 defaultGasLimit = 100000;
vm.prank(provider1);
random.setDefaultGasLimit(defaultGasLimit);
Copy link
Contributor Author

@jayantk jayantk Apr 4, 2025

Choose a reason for hiding this comment

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

these tests now require the provider to opt in to the new flow by setting their gas limit

@@ -703,6 +808,16 @@ abstract contract Entropy is IEntropy, EntropyState {
);
}

// Rounds the provided quantity of gas into units of 10k gas.
// If gas is not evenly divisible by 10k, rounds up.
function roundGas(uint32 gas) internal pure returns (uint16) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

naming doesn't imply it's dividing it by 10k. Maybe something like convertGastoGas10k?

if (gas10k * 10000 < gas) {
gas10k += 1;
}
return SafeCast.toUint16(gas10k);
Copy link
Collaborator

Choose a reason for hiding this comment

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

As a dev, I might set the gas limit to a gazillion just for testing and that would cause a revert here.
I don't think the revert error is easily parsable, so I'd rather test manually and revert with a better reason.

}

uint32 oldGasLimit = provider.defaultGasLimit;
provider.defaultGasLimit = gasLimit;
Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe we should pass this to roundGas and check if it is within the limits and not too high.

@@ -61,6 +63,9 @@ contract EntropyStructs {
bool useBlockhash;
// Status flag for requests with callbacks. See EntropyConstants for the possible values of this flag.
uint8 callbackStatus;
// 2 bytes of space left in this struct.
// The gasLimit in units of 10k gas. (i.e., 2 = 20k gas). We're using units of 10k in order to fit this
// field into the remaining 2 bytes of this storage slot. The dynamic range here is 10k - ~65M, which should
Copy link
Collaborator

Choose a reason for hiding this comment

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

it's actually 655M

// Rounds the provided quantity of gas into units of 10k gas.
// If gas is not evenly divisible by 10k, rounds up.
function roundGas(uint32 gas) internal pure returns (uint16) {
uint32 gas10k = gas / 10000;
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we put this 10000 as a constant somewhere in this file? It's being used 4-5 times across multiple functions.

) {
// This calculation rounds down the fee, which means that users can get some gas in the callback for free.
// However, the value of the free gas is < 1 wei, which is insignificant.
uint128 additionalFee = ((roundedGasLimit -
Copy link
Collaborator

Choose a reason for hiding this comment

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

can't this lead to an underflow? if roundedGasLimit < provider.defaultGasLimit?

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.

2 participants