Commit 2eb69f13 authored by Maurelian's avatar Maurelian

ctb: Fix maxBaseFee calculation, add undeflow check

parent 2f9facab
...@@ -12,6 +12,10 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { ...@@ -12,6 +12,10 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {
bool failedMaxRaiseBaseFeePerBlock; bool failedMaxRaiseBaseFeePerBlock;
bool failedMaxLowerBaseFeePerBlock; bool failedMaxLowerBaseFeePerBlock;
// Used as a special flag for the purpose of identifying unchecked math errors specifically
// in the test contracts, not the target contracts themselves.
bool underflow;
constructor() { constructor() {
initialize(); initialize();
} }
...@@ -74,33 +78,50 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { ...@@ -74,33 +78,50 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {
((uint256(params.prevBaseFee) - cachedPrevBaseFee) < maxBaseFeeChange); ((uint256(params.prevBaseFee) - cachedPrevBaseFee) < maxBaseFeeChange);
} }
// If the last blocked used less than the target amount of gas ensure this block's baseFee // If the last blocked used less than the target amount of gas, (or was empty),
// decreased, but not by more than the max amount // ensure that: this block's baseFee was decreased, but not by more than the max amount
if ( if (
(cachedPrevBoughtGas < uint256(TARGET_RESOURCE_LIMIT)) || (cachedPrevBoughtGas < uint256(TARGET_RESOURCE_LIMIT)) ||
(uint256(params.prevBlockNum) - cachedPrevBlockNum > 1) (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1)
) { ) {
// Invariant: baseFee should decrease
failedLowerBaseFee = failedLowerBaseFee =
failedLowerBaseFee || failedLowerBaseFee ||
(uint256(params.prevBaseFee) > cachedPrevBaseFee); (uint256(params.prevBaseFee) > cachedPrevBaseFee);
if (params.prevBlockNum - cachedPrevBlockNum == 1) { if (params.prevBlockNum - cachedPrevBlockNum == 1) {
// No empty blocks
// Invariant: baseFee should not have decreased by more than the maximum amount
failedMaxLowerBaseFeePerBlock = failedMaxLowerBaseFeePerBlock =
failedMaxLowerBaseFeePerBlock || failedMaxLowerBaseFeePerBlock ||
((cachedPrevBaseFee - uint256(params.prevBaseFee)) < maxBaseFeeChange); ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);
} } else if (params.prevBlockNum - cachedPrevBlockNum > 1) {
// We have at least one empty block
// Update the maxBaseFeeChange to account for multiple blocks having passed // Update the maxBaseFeeChange to account for multiple blocks having passed
maxBaseFeeChange = uint256( unchecked {
Arithmetic.cdexp( maxBaseFeeChange = uint256(
int256(cachedPrevBaseFee), int256(cachedPrevBaseFee) -
BASE_FEE_MAX_CHANGE_DENOMINATOR, Arithmetic.clamp(
int256(uint256(params.prevBlockNum) - cachedPrevBlockNum) Arithmetic.cdexp(
) int256(cachedPrevBaseFee),
); BASE_FEE_MAX_CHANGE_DENOMINATOR,
if (params.prevBlockNum - cachedPrevBlockNum > 1) { int256(uint256(params.prevBlockNum) - cachedPrevBlockNum)
),
MINIMUM_BASE_FEE,
MAXIMUM_BASE_FEE
)
);
}
// Detect an underflow in the previous calculation.
// Without using unchecked above, and detecting the underflow here, echidna would
// otherwise ignore the revert.
underflow = underflow || maxBaseFeeChange > cachedPrevBaseFee;
// Invariant: baseFee should not have decreased by more than the maximum amount
failedMaxLowerBaseFeePerBlock = failedMaxLowerBaseFeePerBlock =
failedMaxLowerBaseFeePerBlock || failedMaxLowerBaseFeePerBlock ||
((cachedPrevBaseFee - uint256(params.prevBaseFee)) < maxBaseFeeChange); ((cachedPrevBaseFee - uint256(params.prevBaseFee)) <= maxBaseFeeChange);
} }
} }
} }
...@@ -130,4 +151,8 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { ...@@ -130,4 +151,8 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {
function echidna_never_exceed_max_decrease() public view returns (bool) { function echidna_never_exceed_max_decrease() public view returns (bool) {
return !failedMaxLowerBaseFeePerBlock; return !failedMaxLowerBaseFeePerBlock;
} }
function echidna_underflow() public view returns (bool) {
return !underflow;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment