Closed sherlock-admin closed 1 year ago
2 comment(s) were left on this issue during the judging contest.
141345 commented:
m
darkart commented:
Keepers take their rewards in Wei so 18 Decimal is correct
When going from 18 decimals -> 6 decimals the values are rounded up which will not lead to amounts where the credited amount is greater than the debited amount.
Escalate
Please take a look at this description of the problem again, which is not described as leading to "amounts where the credited amount is greater than the debited amount."
What this describes is that
keep() -> keeperToken().push(msg.sender, keeperFee);
will fail because there is not enough balance in the contract.Let's take
MultiInvoker.sol
as an example, when the user executes_executeOrder()
there will be the followingkeeperToken
balance changes
Initially MultiInvoker.sol's
keeperToken
balance is 0.Assuming that the
keeperFee = 1_000000_123456789012
calculated inkeep()
is 18 digits. This formula is likely to produce tails larger than 6 digits.UFixed18 keeperFee = UFixed18Lib.from(gasUsed) .mul(multiplier) .add(UFixed18Lib.from(buffer)) .mul(_etherPrice()) .mul(UFixed18.wrap(block.basefee));
Execute
_raiseKeeperFee(keeperFee, data);
, this method to go to the market and get the balance Since this method is 18 -> 6 -> 18, it only gets backkeeperFee = 1_000000_0000000000
, the mantissa is removed. At this point, the balance of MultiInvoker.sol is1_00000000_0000000000
.
keep()
executeskeeperToken().push()
method to transfer the token tomsg.sender
, the quantity passed in this method is still1_000000_123456789012
with full mantissa.That is,
keeperToken().push(msg.sender, 1_000000_123456789012);
But at this point, the contract balance is actually only
1_000000_0000000000
. The balance is not enough, so the transfer will fail.I don't know if this is clear.
You've deleted an escalation for this issue.
bin2chen
medium
keep() may not be able to execute
Summary
Kept.keep()
calls_raiseKeeperFee()
to get the token Most current implementations of_raiseKeeperFee()
remove the trailing number18 -> 6 -> 18
. However, whenKept.keep()
is transferred tomsg.sender
, the trailing number is still included, which may leads to transfer failureVulnerability Detail
Kept.keep()
calls_raiseKeeperFee()
to get the tokenCurrently both
PythOracle
andMultiInvoker
implement the_raiseKeeperFee()
method.Let's take
MultiInvoker_raiseKeeperFee()
for exampleWe can see that
_raiseKeeperFee()
does an interception of the decimal places, removing the ones after 6.18 -> 6 -> 18
.But
keep()
still takes the full number of decimal places.This causes
_raiseKeeperFee()
to get the number of tokens that may be less thankeeperFee
causingkeeperToken().push(msg.sender, keeperFee);
to failImpact
keep()
may not perform properlyCode Snippet
https://github.com/sherlock-audit/2023-07-perennial/blob/main/root/contracts/attribute/Kept.sol#L54C1-L54C1
Tool used
Manual Review
Recommendation
Keep()
removes decimals after the 6th digit, as usual.