Source: https://github.com/sherlock-audit/2024-04-xkeeper-judging/issues/57
The protocol has acknowledged this issue.
IllIllI, Kirkeelee, Kose, LTDingZhen, s1ce
L1 data fees are not reimbursed, and they are often orders of magnitude more expensive than the L2 gas fees being reimbursed. Not reimbursing these fees will lead to jobs not being executed on L2s.
While the contest README says that the protocol is interested in all EVM-compatible chains, its not clear to what extent they need compatibility. For instance, many chains have workarounds for the fact that they need to publish data from the L2 to the L1 via calldata, and therefore charge for those operations directly. Such caveats indicate that the compatibility is not 100% and therefore we can't really assume that any random chain will be supported. However, the README explicitly mentions Optimism as a target chain, so its idiosyncracies are in-scope.
The Gelato protocol properly handles L1 data fees, but neither Keep3r nor OpenRelay do. It could be argued that for Keep3r, it's possible to modify a job's fee rate dynamically and therefore it's not that big a risk, but for OpenRelay, the reimbursement formula is hard-coded, which means there's no workaround.
Looking at a transaction from this vault, the transaction cost was 0.000305237594921218 ETH ($1.17) but only 0.00000008929694256 ETH (<$0.01) was reimbursed. The L1 data fee was 0.000304676890061656 Eth, whereas the gas fee was 0.000000111805735391.
As is shown in this analysis for another contest, the two fees do not have a fixed ratio, and the L1 data fee is frequently much larger than the L2 gas fee, for extended periods of time. This essentially means that the protocol is broken on L2s for any use case which requires timely executions. The contest README states that the sponsor is interested in issues where future integrations would be negatively impacted, and one such case would be where an exchange is trying to use xkeeper to handle customer operations, as is outlined at the end of the linked-to comment above. Operations will appear to hang for multiple hours at a time, causing loss of funds for customers trying to close their orders.
Only the L2 gas is reimbursed, not any of the L1 data fees:
// File: solidity/contracts/relays/OpenRelay.sol : OpenRelay.exec() #1
28 // Execute the automation vault counting the gas spent
29 uint256 _initialGas = gasleft();
30 _automationVault.exec(msg.sender, _execData, new IAutomationVault.FeeData[](0));
31 uint256 _gasSpent = _initialGas - gasleft();
32
33 // Calculate the payment for the relayer
34 uint256 _payment = (_gasSpent + GAS_BONUS) * block.basefee * GAS_MULTIPLIER / BASE;
35
36 // Send the payment to the relayer
37 IAutomationVault.FeeData[] memory _feeData = new IAutomationVault.FeeData[](1);
38 _feeData[0] = IAutomationVault.FeeData(_feeRecipient, _NATIVE_TOKEN, _payment);
39: _automationVault.exec(msg.sender, new IAutomationVault.ExecData[](0), _feeData);
Manual Review
Every L2 has its own formula for calculating the L1 data fee, so different versions of the code will have to be written for each L2. This is the description for Optimism. Note that the Ecotone upgrade has occurred, so be sure to implement based on those or these instructions.
sherlock-admin2
1 comment(s) were left on this issue during the judging contest.
Kose commented:
medium
realfugazzi
Why is this an issue? This is not the responsibility of the OpenRelay contract.
adam-idarrha
@realfugazzi because that contract is in scope , and written by xkeeper .
realfugazzi
@IllIllI000 how is this not a feature request, according to your logic?
You are stating that L1 fees are not reimbursed, but there is no place where this is posted as protocol requirement. Job executioners will simulate the op and see if reimbursement is fit for them. Looks like a feature request then, correct?
ashitakah
I agree, it is true that the payments in L2 would be too low to incentivize the work and we are working on improving the system, but it is not a vulnerability and continues to pay although in a residual way.
IllIllI000
@ashitakah isn't "too low to incentivize the work" a future integration issue for any project looking to use xkeeper on an L2?
BoRonG0d
Contest readme explicitly states that the contract will be deployed on OP mainnet, and ALL information watson received during the competition did not indicate that OpenRelay would be used as future integration. So this is a valid issue.
And, this was judged as high in the past:
https://github.com/sherlock-audit/2023-07-perennial-judging/issues/91
Source: https://github.com/sherlock-audit/2024-04-xkeeper-judging/issues/132
Kose
Keep3rRelay
and Keep3rBondedRelay
uses deprecated function for sidechains and exec
calls will always revert.
Keep3r takes different arguments for function worked()
in sidechains in order to estimate gas usage and rewards for keepers properly:
/// @dev Sidechain implementation deprecates worked(address) as it should come with a usdPerGasUnit parameter
function worked(address) external pure override {
revert Deprecated();
}
/// @notice Implemented by jobs to show that a keeper performed work
/// @dev Uses a USD per gas unit payment mechanism
/// @param _keeper Address of the keeper that performed the work
/// @param _usdPerGasUnit Units of USD (in wei) per gas unit that should be rewarded to the keeper
function worked(address _keeper, uint256 _usdPerGasUnit) external override {
The snippet above taken from Keep3rSidechain.sol that is live in optimism currently. We can also see that this contract is exact contract that will be interacted as it is the address of KEEPER_V2
in deployed Keep3r Relays by xKeeper in Optimism. Deployed addresses can checked from here
But relay contracts implemented by xKeeper uses the worked()
function that is deprecated:
// Inject the final call which will issue the payment to the keeper
_execDataKeep3r[_execDataLength + 1] = IAutomationVault.ExecData({
job: address(KEEP3R_V2),
jobData: abi.encodeWithSelector(IKeep3rV2.worked.selector, msg.sender)
});
Hence in chains other than mainnet, Keep3r calls will always revert.
Current Keep3r Relay contracts are not compatible with Keep3r in Optimism (Keeper is only deployed to Mainnet and Optimism currently). Although vault creation will succeed, exec()
called by keepers will always revert.
Keep3rRelay.sol Keep3rBondedRelay.sol
Manual Review
Either implement a compatible version for Keep3rSideChain, or don't use Keep3r in sidechains.
sherlock-admin3
1 comment(s) were left on this issue during the judging contest.
Kose commented:
medium
Hash01011122
Borderline Low/Med issue
kosedogus
Escalate
The core contract functionality is broken for Keep3rRelay.sol
and Keep3rBondedRelay.sol
in all L2's. All exec()
calls via these contracts will always revert, rendering contracts useless. This should be valid medium.
sherlock-admin2
Escalate
The core contract functionality is broken for
Keep3rRelay.sol
andKeep3rBondedRelay.sol
in all L2's. Allexec()
calls via these contracts will always revert, rendering contracts useless. This should be valid medium.
You've created a valid escalation!
To remove the escalation from consideration: Delete your comment.
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
ashitakah
The issue is right, in the L2 version of keep3r worked was deprecated, we have to generate versions of the keep3r relays in L2 with the updated worked.
Hash01011122
As I mentioned, above this issue is borderline low/medium issue. In earlier contest of sherlock, issues like this was considered as low severity issue, because of which I considered it as low. I will let head of judge decide the severity.
cvetanovv
For me this issue is Medium and fits the rule:
Breaks core contract functionality, rendering the contract useless.
I am planning to accept the escalation and make this issue Medium.
Evert0x
Result: Medium Unique
sherlock-admin2
Escalations have been resolved successfully!
Escalation status:
sherlock-admin2
The protocol team fixed this issue in the following PRs/commits: https://github.com/xkeeper-framework/xkeeper-core/commit/df7b21882a1073b334625a1be394e38a2bba1cb9