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(pulse): add pulse contracts #2090

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

feat(pulse): add pulse contracts #2090

wants to merge 28 commits into from

Conversation

cctdaniel
Copy link
Contributor

No description provided.

Copy link

vercel bot commented Nov 4, 2024

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

Name Status Preview Comments Updated (UTC)
api-reference ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 17, 2025 3:49am
proposals ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 17, 2025 3:49am
staking ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 17, 2025 3:49am
2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
component-library ⬜️ Ignored (Inspect) Visit Preview Jan 17, 2025 3:49am
insights ⬜️ Ignored (Inspect) Visit Preview Jan 17, 2025 3:49am

@cctdaniel cctdaniel marked this pull request as draft November 4, 2024 14:11
Copy link
Contributor

@jayantk jayantk left a comment

Choose a reason for hiding this comment

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

I have a couple comments on this, but I think this is fine to merge and then we can iterate on top.

// Check if enough gas remains for the callback plus 50% overhead for cross-contract call (uses integer arithmetic to avoid floating point)
if (gasleft() < (req.callbackGasLimit * 3) / 2) {
revert InsufficientGas();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

why do you need this check? Why not just run the rest of the code, and then either you run out of gas or you don't?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i think it just provides better UX by failing early with a clear error message, also actual gas paid is gas used

there might be a situation where:

  • user provides exactly callbackGasLimit to pulseCallback
  • gasleft() is also callbackGasLimit
  • we don't have enough gas for events/cleanup
  • transaction fails with generic out-of-gas error

Comment on lines +146 to +170
function getFee(
uint256 callbackGasLimit
) public view override returns (uint128 feeAmount) {
uint128 baseFee = _state.pythFeeInWei;
uint256 gasFee = callbackGasLimit * tx.gasprice;
feeAmount = baseFee + SafeCast.toUint128(gasFee);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

In Entropy, the keeper updates its fee over time.

I think the thing to do here is to give the keeper a configurable feePerGas parameter instead of tx.gasprice. The keeper then sets both a base fee and the feePerGas so it's a linear ax+b pricing model and then we can figure out how to do this properly off chain.

interface IPulseConsumer {
function pulseCallback(
uint64 sequenceNumber,
address updater,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should have provider but if you don't have provider i don't think you need this parameter either.

req.requester,
"low-level error (possibly out of gas)"
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you want these catches either. If either of these errors happens for a transient reason, it means the callback can't be called in the future.

In entropy if a callback fails, we leave the request open. It could get fulfilled later, or it could just sit there forever.

Copy link
Contributor

Choose a reason for hiding this comment

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

(this is actually important. In practice, we have callbacks that error on the first try and then succeed on a later retry)

Copy link
Contributor

@jayantk jayantk Jan 15, 2025

Choose a reason for hiding this comment

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

Oh you also need to use the Check-Effects-Interactions pattern here, meaning the clearRequest call (the effect) needs to happen before cross-contract calls (interactions). There's a whole class of security vulnerabilities if you don't do the interactions last, because the cross-contract call can call back into the Pulse contract and then weird stuff can happen.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the reason why we have this try-catch is because @m30m said that in entropy it's difficult to know if its the user error or our error so logging this will provide better UX, we can document that the callback contract should not fail, and if it fails we wont retry

SafeCast.toUint64(req.publishTime)
);

// Check if enough gas remains for the callback plus 50% overhead for cross-contract call (uses integer arithmetic to avoid floating point)
Copy link
Collaborator

Choose a reason for hiding this comment

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

i think 50% overhead is too much, the overhead is mostly constant.

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.

4 participants