Commit e0c5cb1c authored by Mark Tyneway's avatar Mark Tyneway

contracts-bedrock: modularize deposit resource config

parent 0446d83b
...@@ -4,6 +4,7 @@ pragma solidity 0.8.15; ...@@ -4,6 +4,7 @@ pragma solidity 0.8.15;
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { SafeCall } from "../libraries/SafeCall.sol"; import { SafeCall } from "../libraries/SafeCall.sol";
import { L2OutputOracle } from "./L2OutputOracle.sol"; import { L2OutputOracle } from "./L2OutputOracle.sol";
import { SystemConfig } from "./SystemConfig.sol";
import { Constants } from "../libraries/Constants.sol"; import { Constants } from "../libraries/Constants.sol";
import { Types } from "../libraries/Types.sol"; import { Types } from "../libraries/Types.sol";
import { Hashing } from "../libraries/Hashing.sol"; import { Hashing } from "../libraries/Hashing.sol";
...@@ -48,6 +49,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -48,6 +49,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
*/ */
L2OutputOracle public immutable L2_ORACLE; L2OutputOracle public immutable L2_ORACLE;
/**
*
*/
SystemConfig public immutable SYSTEM_CONFIG;
/** /**
* @notice Address that has the ability to pause and unpause withdrawals. * @notice Address that has the ability to pause and unpause withdrawals.
*/ */
...@@ -135,19 +141,22 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -135,19 +141,22 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
} }
/** /**
* @custom:semver 1.2.0 * @custom:semver 1.3.0
* *
* @param _l2Oracle Address of the L2OutputOracle contract. * @param _l2Oracle Address of the L2OutputOracle contract.
* @param _guardian Address that can pause deposits and withdrawals. * @param _guardian Address that can pause deposits and withdrawals.
* @param _paused Sets the contract's pausability state. * @param _paused Sets the contract's pausability state.
* @param _config Address of the SystemConfig contract.
*/ */
constructor( constructor(
L2OutputOracle _l2Oracle, L2OutputOracle _l2Oracle,
address _guardian, address _guardian,
bool _paused bool _paused,
) Semver(1, 2, 0) { SystemConfig _config
) Semver(1, 3, 0) {
L2_ORACLE = _l2Oracle; L2_ORACLE = _l2Oracle;
GUARDIAN = _guardian; GUARDIAN = _guardian;
SYSTEM_CONFIG = _config;
initialize(_paused); initialize(_paused);
} }
...@@ -197,6 +206,30 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -197,6 +206,30 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
// Intentionally empty. // Intentionally empty.
} }
// TODO: I don't like having so many return args but I also don't like
// wrapping them into a struct
function resourceConfig() public view override returns (SystemConfig.ResourceConfig memory) {
(
uint32 maxResourceLimit,
uint8 elasticityMultiplier,
uint8 baseFeeMaxChangeDenominator,
uint32 minimumBaseFee,
uint32 systemTxMaxGas,
uint128 maximumBaseFee
) = SYSTEM_CONFIG.resourceConfig();
SystemConfig.ResourceConfig memory config = SystemConfig.ResourceConfig({
maxResourceLimit: maxResourceLimit,
elasticityMultiplier: elasticityMultiplier,
baseFeeMaxChangeDenominator: baseFeeMaxChangeDenominator,
minimumBaseFee: minimumBaseFee,
systemTxMaxGas: systemTxMaxGas,
maximumBaseFee: maximumBaseFee
});
return config;
}
/** /**
* @notice Proves a withdrawal transaction. * @notice Proves a withdrawal transaction.
* *
......
...@@ -5,6 +5,7 @@ import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable ...@@ -5,6 +5,7 @@ import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
import { Burn } from "../libraries/Burn.sol"; import { Burn } from "../libraries/Burn.sol";
import { Arithmetic } from "../libraries/Arithmetic.sol"; import { Arithmetic } from "../libraries/Arithmetic.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
/** /**
* @custom:upgradeable * @custom:upgradeable
...@@ -27,46 +28,6 @@ abstract contract ResourceMetering is Initializable { ...@@ -27,46 +28,6 @@ abstract contract ResourceMetering is Initializable {
uint64 prevBlockNum; uint64 prevBlockNum;
} }
/**
* @notice Maximum amount of the resource that can be used within this block.
* This value cannot be larger than the L2 block gas limit.
*/
int256 public constant MAX_RESOURCE_LIMIT = 20_000_000;
/**
* @notice Along with the resource limit, determines the target resource limit.
*/
int256 public constant ELASTICITY_MULTIPLIER = 10;
/**
* @notice Target amount of the resource that should be used within this block.
*/
int256 public constant TARGET_RESOURCE_LIMIT = MAX_RESOURCE_LIMIT / ELASTICITY_MULTIPLIER;
/**
* @notice Denominator that determines max change on fee per block.
*/
int256 public constant BASE_FEE_MAX_CHANGE_DENOMINATOR = 8;
/**
* @notice Minimum base fee value, cannot go lower than this.
*/
int256 public constant MINIMUM_BASE_FEE = 1 gwei;
/**
* @notice Maximum base fee value, cannot go higher than this.
* It is possible for the MAXIMUM_BASE_FEE to raise to a value
* that is so large it will consume the entire gas limit of
* an L1 block.
*/
int256 public constant MAXIMUM_BASE_FEE = int256(uint256(type(uint128).max));
/**
* @notice Initial base fee value. This value must be smaller than the
* MAXIMUM_BASE_FEE.
*/
uint128 public constant INITIAL_BASE_FEE = 1 gwei;
/** /**
* @notice EIP-1559 style gas parameters. * @notice EIP-1559 style gas parameters.
*/ */
...@@ -102,20 +63,24 @@ abstract contract ResourceMetering is Initializable { ...@@ -102,20 +63,24 @@ abstract contract ResourceMetering is Initializable {
function _metered(uint64 _amount, uint256 _initialGas) internal { function _metered(uint64 _amount, uint256 _initialGas) internal {
// Update block number and base fee if necessary. // Update block number and base fee if necessary.
uint256 blockDiff = block.number - params.prevBlockNum; uint256 blockDiff = block.number - params.prevBlockNum;
SystemConfig.ResourceConfig memory config = resourceConfig();
int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) / int256(uint256(config.elasticityMultiplier));
if (blockDiff > 0) { if (blockDiff > 0) {
// Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate
// at which deposits can be created and therefore limit the potential for deposits to // at which deposits can be created and therefore limit the potential for deposits to
// spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes. // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes.
int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - TARGET_RESOURCE_LIMIT; int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit;
int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) / int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) /
(TARGET_RESOURCE_LIMIT * BASE_FEE_MAX_CHANGE_DENOMINATOR); (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator)));
// Update base fee by adding the base fee delta and clamp the resulting value between // Update base fee by adding the base fee delta and clamp the resulting value between
// min and max. // min and max.
int256 newBaseFee = Arithmetic.clamp({ int256 newBaseFee = Arithmetic.clamp({
_value: int256(uint256(params.prevBaseFee)) + baseFeeDelta, _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta,
_min: MINIMUM_BASE_FEE, _min: int256(uint256(config.minimumBaseFee)),
_max: MAXIMUM_BASE_FEE _max: int256(uint256(config.maximumBaseFee))
}); });
// If we skipped more than one block, we also need to account for every empty block. // If we skipped more than one block, we also need to account for every empty block.
...@@ -128,11 +93,11 @@ abstract contract ResourceMetering is Initializable { ...@@ -128,11 +93,11 @@ abstract contract ResourceMetering is Initializable {
newBaseFee = Arithmetic.clamp({ newBaseFee = Arithmetic.clamp({
_value: Arithmetic.cdexp({ _value: Arithmetic.cdexp({
_coefficient: newBaseFee, _coefficient: newBaseFee,
_denominator: BASE_FEE_MAX_CHANGE_DENOMINATOR, _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)),
_exponent: int256(blockDiff - 1) _exponent: int256(blockDiff - 1)
}), }),
_min: MINIMUM_BASE_FEE, _min: int256(uint256(config.minimumBaseFee)),
_max: MAXIMUM_BASE_FEE _max: int256(uint256(config.maximumBaseFee))
}); });
} }
...@@ -145,7 +110,7 @@ abstract contract ResourceMetering is Initializable { ...@@ -145,7 +110,7 @@ abstract contract ResourceMetering is Initializable {
// Make sure we can actually buy the resource amount requested by the user. // Make sure we can actually buy the resource amount requested by the user.
params.prevBoughtGas += _amount; params.prevBoughtGas += _amount;
require( require(
int256(uint256(params.prevBoughtGas)) <= MAX_RESOURCE_LIMIT, int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)),
"ResourceMetering: cannot buy more gas than available gas limit" "ResourceMetering: cannot buy more gas than available gas limit"
); );
...@@ -168,14 +133,21 @@ abstract contract ResourceMetering is Initializable { ...@@ -168,14 +133,21 @@ abstract contract ResourceMetering is Initializable {
} }
} }
/**
* @notice
*/
function resourceConfig() public virtual returns (SystemConfig.ResourceConfig memory);
/** /**
* @notice Sets initial resource parameter values. This function must either be called by the * @notice Sets initial resource parameter values. This function must either be called by the
* initializer function of an upgradeable child contract. * initializer function of an upgradeable child contract.
*/ */
// solhint-disable-next-line func-name-mixedcase // solhint-disable-next-line func-name-mixedcase
function __ResourceMetering_init() internal onlyInitializing { function __ResourceMetering_init() internal onlyInitializing {
SystemConfig.ResourceConfig memory config = resourceConfig();
params = ResourceParams({ params = ResourceParams({
prevBaseFee: INITIAL_BASE_FEE, prevBaseFee: config.minimumBaseFee,
prevBoughtGas: 0, prevBoughtGas: 0,
prevBlockNum: uint64(block.number) prevBlockNum: uint64(block.number)
}); });
......
...@@ -26,7 +26,20 @@ contract SystemConfig is OwnableUpgradeable, Semver { ...@@ -26,7 +26,20 @@ contract SystemConfig is OwnableUpgradeable, Semver {
BATCHER, BATCHER,
GAS_CONFIG, GAS_CONFIG,
GAS_LIMIT, GAS_LIMIT,
UNSAFE_BLOCK_SIGNER UNSAFE_BLOCK_SIGNER,
RESOURCE_CONFIG
}
/**
* @notice
*/
struct ResourceConfig {
uint32 maxResourceLimit;
uint8 elasticityMultiplier;
uint8 baseFeeMaxChangeDenominator;
uint32 minimumBaseFee;
uint32 systemTxMaxGas;
uint128 maximumBaseFee;
} }
/** /**
...@@ -69,6 +82,8 @@ contract SystemConfig is OwnableUpgradeable, Semver { ...@@ -69,6 +82,8 @@ contract SystemConfig is OwnableUpgradeable, Semver {
*/ */
uint64 public gasLimit; uint64 public gasLimit;
ResourceConfig public resourceConfig;
/** /**
* @notice Emitted when configuration is updated * @notice Emitted when configuration is updated
* *
...@@ -79,7 +94,7 @@ contract SystemConfig is OwnableUpgradeable, Semver { ...@@ -79,7 +94,7 @@ contract SystemConfig is OwnableUpgradeable, Semver {
event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);
/** /**
* @custom:semver 1.0.1 * @custom:semver 1.1.0
* *
* @param _owner Initial owner of the contract. * @param _owner Initial owner of the contract.
* @param _overhead Initial overhead value. * @param _overhead Initial overhead value.
...@@ -95,12 +110,22 @@ contract SystemConfig is OwnableUpgradeable, Semver { ...@@ -95,12 +110,22 @@ contract SystemConfig is OwnableUpgradeable, Semver {
bytes32 _batcherHash, bytes32 _batcherHash,
uint64 _gasLimit, uint64 _gasLimit,
address _unsafeBlockSigner address _unsafeBlockSigner
) Semver(1, 0, 1) { ) Semver(1, 1, 0) {
initialize(_owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner); ResourceConfig memory config = ResourceConfig({
maxResourceLimit: 20_000_000,
elasticityMultiplier: 10,
baseFeeMaxChangeDenominator: 8,
minimumBaseFee: 1 gwei,
systemTxMaxGas: 1_000_000,
maximumBaseFee: type(uint128).max
});
initialize(_owner, _overhead, _scalar, _batcherHash, _gasLimit, _unsafeBlockSigner, config);
} }
/** /**
* @notice Initializer. * @notice Initializer. The resource config must be set before the
* require check.
* *
* @param _owner Initial owner of the contract. * @param _owner Initial owner of the contract.
* @param _overhead Initial overhead value. * @param _overhead Initial overhead value.
...@@ -115,9 +140,9 @@ contract SystemConfig is OwnableUpgradeable, Semver { ...@@ -115,9 +140,9 @@ contract SystemConfig is OwnableUpgradeable, Semver {
uint256 _scalar, uint256 _scalar,
bytes32 _batcherHash, bytes32 _batcherHash,
uint64 _gasLimit, uint64 _gasLimit,
address _unsafeBlockSigner address _unsafeBlockSigner,
ResourceConfig memory _resourceConfig
) public initializer { ) public initializer {
require(_gasLimit >= MINIMUM_GAS_LIMIT, "SystemConfig: gas limit too low");
__Ownable_init(); __Ownable_init();
transferOwnership(_owner); transferOwnership(_owner);
overhead = _overhead; overhead = _overhead;
...@@ -125,6 +150,8 @@ contract SystemConfig is OwnableUpgradeable, Semver { ...@@ -125,6 +150,8 @@ contract SystemConfig is OwnableUpgradeable, Semver {
batcherHash = _batcherHash; batcherHash = _batcherHash;
gasLimit = _gasLimit; gasLimit = _gasLimit;
_setUnsafeBlockSigner(_unsafeBlockSigner); _setUnsafeBlockSigner(_unsafeBlockSigner);
_setResourceConfig(_resourceConfig);
require(_gasLimit >= minimumGasLimit(), "SystemConfig: gas limit too low");
} }
/** /**
...@@ -188,7 +215,7 @@ contract SystemConfig is OwnableUpgradeable, Semver { ...@@ -188,7 +215,7 @@ contract SystemConfig is OwnableUpgradeable, Semver {
* @param _gasLimit New gas limit. * @param _gasLimit New gas limit.
*/ */
function setGasLimit(uint64 _gasLimit) external onlyOwner { function setGasLimit(uint64 _gasLimit) external onlyOwner {
require(_gasLimit >= MINIMUM_GAS_LIMIT, "SystemConfig: gas limit too low"); require(_gasLimit >= minimumGasLimit(), "SystemConfig: gas limit too low");
gasLimit = _gasLimit; gasLimit = _gasLimit;
bytes memory data = abi.encode(_gasLimit); bytes memory data = abi.encode(_gasLimit);
...@@ -197,7 +224,7 @@ contract SystemConfig is OwnableUpgradeable, Semver { ...@@ -197,7 +224,7 @@ contract SystemConfig is OwnableUpgradeable, Semver {
/** /**
* @notice Low level setter for the unsafe block signer address. This function exists to * @notice Low level setter for the unsafe block signer address. This function exists to
* deduplicate code around storing the unsafeBlockSigner address in storage. * deduplicate code arou,nd storing the unsafeBlockSigner address in storage.
* *
* @param _unsafeBlockSigner New unsafeBlockSigner value. * @param _unsafeBlockSigner New unsafeBlockSigner value.
*/ */
...@@ -207,4 +234,23 @@ contract SystemConfig is OwnableUpgradeable, Semver { ...@@ -207,4 +234,23 @@ contract SystemConfig is OwnableUpgradeable, Semver {
sstore(slot, _unsafeBlockSigner) sstore(slot, _unsafeBlockSigner)
} }
} }
function setResourceConfig(ResourceConfig memory _config) external onlyOwner {
_setResourceConfig(_config);
bytes memory data = abi.encode(_config);
emit ConfigUpdate(VERSION, UpdateType.RESOURCE_CONFIG, data);
}
function _setResourceConfig(ResourceConfig memory _config) internal {
require(_config.minimumBaseFee <= _config.maximumBaseFee);
require(_config.baseFeeMaxChangeDenominator > 0);
require(_config.maxResourceLimit + _config.systemTxMaxGas <= gasLimit);
resourceConfig = _config;
}
function minimumGasLimit() public view returns (uint256) {
return resourceConfig.maxResourceLimit + resourceConfig.systemTxMaxGas;
}
} }
...@@ -79,6 +79,7 @@ contract SystemDictator is OwnableUpgradeable { ...@@ -79,6 +79,7 @@ contract SystemDictator is OwnableUpgradeable {
bytes32 batcherHash; bytes32 batcherHash;
uint64 gasLimit; uint64 gasLimit;
address unsafeBlockSigner; address unsafeBlockSigner;
SystemConfig.ResourceConfig resourceConfig;
} }
/** /**
...@@ -160,6 +161,15 @@ contract SystemDictator is OwnableUpgradeable { ...@@ -160,6 +161,15 @@ contract SystemDictator is OwnableUpgradeable {
* initialized upon deployment. * initialized upon deployment.
*/ */
constructor() { constructor() {
SystemConfig.ResourceConfig memory rcfg = SystemConfig.ResourceConfig({
maxResourceLimit: 20_000_000,
elasticityMultiplier: 10,
baseFeeMaxChangeDenominator: 8,
minimumBaseFee: 1 gwei,
systemTxMaxGas: 1_000_000,
maximumBaseFee: type(uint128).max
});
// Using this shorter variable as an alias for address(0) just prevents us from having to // Using this shorter variable as an alias for address(0) just prevents us from having to
// to use a new line for every single parameter. // to use a new line for every single parameter.
address zero = address(0); address zero = address(0);
...@@ -177,7 +187,7 @@ contract SystemDictator is OwnableUpgradeable { ...@@ -177,7 +187,7 @@ contract SystemDictator is OwnableUpgradeable {
PortalSender(zero), PortalSender(zero),
SystemConfig(zero) SystemConfig(zero)
), ),
SystemConfigConfig(zero, 0, 0, bytes32(0), 0, zero) SystemConfigConfig(zero, 0, 0, bytes32(0), 0, zero, rcfg)
) )
); );
} }
...@@ -244,7 +254,8 @@ contract SystemDictator is OwnableUpgradeable { ...@@ -244,7 +254,8 @@ contract SystemDictator is OwnableUpgradeable {
config.systemConfigConfig.scalar, config.systemConfigConfig.scalar,
config.systemConfigConfig.batcherHash, config.systemConfigConfig.batcherHash,
config.systemConfigConfig.gasLimit, config.systemConfigConfig.gasLimit,
config.systemConfigConfig.unsafeBlockSigner config.systemConfigConfig.unsafeBlockSigner,
config.systemConfigConfig.resourceConfig
) )
) )
); );
......
...@@ -3,16 +3,27 @@ pragma solidity 0.8.15; ...@@ -3,16 +3,27 @@ pragma solidity 0.8.15;
import { OptimismPortal } from "../L1/OptimismPortal.sol"; import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol"; import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol"; import { AddressAliasHelper } from "../vendor/AddressAliasHelper.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
contract EchidnaFuzzOptimismPortal { contract EchidnaFuzzOptimismPortal {
OptimismPortal internal portal; OptimismPortal internal portal;
bool internal failedToComplete; bool internal failedToComplete;
constructor() { constructor() {
SystemConfig config = new SystemConfig({
_owner: address(0),
_overhead: 0,
_scalar: 10000,
_batcherHash: bytes32(0),
_gasLimit: 30_000_000,
_unsafeBlockSigner: address(0)
});
portal = new OptimismPortal({ portal = new OptimismPortal({
_l2Oracle: L2OutputOracle(address(0)), _l2Oracle: L2OutputOracle(address(0)),
_guardian: address(0), _guardian: address(0),
_paused: false _paused: false,
_config: config
}); });
} }
......
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { ResourceMetering } from "../L1/ResourceMetering.sol"; import { ResourceMetering } from "../L1/ResourceMetering.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
import { Arithmetic } from "../libraries/Arithmetic.sol"; import { Arithmetic } from "../libraries/Arithmetic.sol";
import { StdUtils } from "forge-std/Test.sol"; import { StdUtils } from "forge-std/Test.sol";
...@@ -24,6 +25,18 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { ...@@ -24,6 +25,18 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {
__ResourceMetering_init(); __ResourceMetering_init();
} }
function resourceConfig() public pure override returns (SystemConfig.ResourceConfig memory) {
SystemConfig.ResourceConfig memory config = SystemConfig.ResourceConfig({
maxResourceLimit: 20_000_000,
elasticityMultiplier: 10,
baseFeeMaxChangeDenominator: 8,
minimumBaseFee: 1 gwei,
systemTxMaxGas: 1_000_000,
maximumBaseFee: type(uint128).max
});
return config;
}
/** /**
* @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test * @notice Takes the necessary parameters to allow us to burn arbitrary amounts of gas to test
* the underlying resource metering/gas market logic * the underlying resource metering/gas market logic
...@@ -34,12 +47,15 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { ...@@ -34,12 +47,15 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {
uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas); uint256 cachedPrevBoughtGas = uint256(params.prevBoughtGas);
uint256 cachedPrevBlockNum = uint256(params.prevBlockNum); uint256 cachedPrevBlockNum = uint256(params.prevBlockNum);
SystemConfig.ResourceConfig memory rcfg = resourceConfig();
uint256 targetResourceLimit = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier);
// check that the last block's base fee hasn't dropped below the minimum // check that the last block's base fee hasn't dropped below the minimum
if (cachedPrevBaseFee < uint256(MINIMUM_BASE_FEE)) { if (cachedPrevBaseFee < uint256(rcfg.minimumBaseFee)) {
failedNeverBelowMinBaseFee = true; failedNeverBelowMinBaseFee = true;
} }
// check that the last block didn't consume more than the max amount of gas // check that the last block didn't consume more than the max amount of gas
if (cachedPrevBoughtGas > uint256(MAX_RESOURCE_LIMIT)) { if (cachedPrevBoughtGas > uint256(rcfg.maxResourceLimit)) {
failedMaxGasPerBlock = true; failedMaxGasPerBlock = true;
} }
...@@ -51,11 +67,11 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { ...@@ -51,11 +67,11 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {
if (_raiseBaseFee) { if (_raiseBaseFee) {
gasToBurn = bound( gasToBurn = bound(
_gasToBurn, _gasToBurn,
uint256(TARGET_RESOURCE_LIMIT), uint256(targetResourceLimit),
uint256(MAX_RESOURCE_LIMIT) uint256(rcfg.maxResourceLimit)
); );
} else { } else {
gasToBurn = bound(_gasToBurn, 0, uint256(TARGET_RESOURCE_LIMIT)); gasToBurn = bound(_gasToBurn, 0, targetResourceLimit);
} }
_burnInternal(uint64(gasToBurn)); _burnInternal(uint64(gasToBurn));
...@@ -63,13 +79,13 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { ...@@ -63,13 +79,13 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {
// Part 3: we run checks and modify our invariant flags based on the updated params values // Part 3: we run checks and modify our invariant flags based on the updated params values
// Calculate the maximum allowed baseFee change (per block) // Calculate the maximum allowed baseFee change (per block)
uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(BASE_FEE_MAX_CHANGE_DENOMINATOR); uint256 maxBaseFeeChange = cachedPrevBaseFee / uint256(rcfg.baseFeeMaxChangeDenominator);
// If the last block used more than the target amount of gas (and there were no // If the last block used more than the target amount of gas (and there were no
// empty blocks in between), ensure this block's baseFee increased, but not by // empty blocks in between), ensure this block's baseFee increased, but not by
// more than the max amount per block // more than the max amount per block
if ( if (
(cachedPrevBoughtGas > uint256(TARGET_RESOURCE_LIMIT)) && (cachedPrevBoughtGas > uint256(targetResourceLimit)) &&
(uint256(params.prevBlockNum) - cachedPrevBlockNum == 1) (uint256(params.prevBlockNum) - cachedPrevBlockNum == 1)
) { ) {
failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee); failedRaiseBaseFee = failedRaiseBaseFee || (params.prevBaseFee <= cachedPrevBaseFee);
...@@ -81,7 +97,7 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { ...@@ -81,7 +97,7 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {
// If the last block used less than the target amount of gas, (or was empty), // If the last block used less than the target amount of gas, (or was empty),
// ensure that: this block's baseFee was 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(targetResourceLimit)) ||
(uint256(params.prevBlockNum) - cachedPrevBlockNum > 1) (uint256(params.prevBlockNum) - cachedPrevBlockNum > 1)
) { ) {
// Invariant: baseFee should decrease // Invariant: baseFee should decrease
...@@ -104,11 +120,11 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils { ...@@ -104,11 +120,11 @@ contract EchidnaFuzzResourceMetering is ResourceMetering, StdUtils {
Arithmetic.clamp( Arithmetic.clamp(
Arithmetic.cdexp( Arithmetic.cdexp(
int256(cachedPrevBaseFee), int256(cachedPrevBaseFee),
BASE_FEE_MAX_CHANGE_DENOMINATOR, int256(uint256(rcfg.baseFeeMaxChangeDenominator)),
int256(uint256(params.prevBlockNum) - cachedPrevBlockNum) int256(uint256(params.prevBlockNum) - cachedPrevBlockNum)
), ),
MINIMUM_BASE_FEE, int256(uint256(rcfg.minimumBaseFee)),
MAXIMUM_BASE_FEE int256(uint256(rcfg.maximumBaseFee))
) )
); );
} }
......
...@@ -32,8 +32,6 @@ contract SetPrevBaseFee_Test is Portal_Initializer { ...@@ -32,8 +32,6 @@ contract SetPrevBaseFee_Test is Portal_Initializer {
// In order to achieve this we make no assertions, and handle everything else in the setUp() // In order to achieve this we make no assertions, and handle everything else in the setUp()
// function. // function.
contract GasBenchMark_OptimismPortal is Portal_Initializer { contract GasBenchMark_OptimismPortal is Portal_Initializer {
uint128 internal INITIAL_BASE_FEE;
// Reusable default values for a test withdrawal // Reusable default values for a test withdrawal
Types.WithdrawalTransaction _defaultTx; Types.WithdrawalTransaction _defaultTx;
...@@ -86,8 +84,6 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer { ...@@ -86,8 +84,6 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer {
1 1
); );
INITIAL_BASE_FEE = op.INITIAL_BASE_FEE();
// Fund the portal so that we can withdraw ETH. // Fund the portal so that we can withdraw ETH.
vm.deal(address(op), 0xFFFFFFFF); vm.deal(address(op), 0xFFFFFFFF);
} }
...@@ -103,7 +99,7 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer { ...@@ -103,7 +99,7 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer {
} }
function test_depositTransaction_benchmark_1() external { function test_depositTransaction_benchmark_1() external {
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE); setPrevBaseFee(vm, address(op), 1 gwei);
op.depositTransaction{ value: NON_ZERO_VALUE }( op.depositTransaction{ value: NON_ZERO_VALUE }(
NON_ZERO_ADDRESS, NON_ZERO_ADDRESS,
ZERO_VALUE, ZERO_VALUE,
...@@ -124,16 +120,9 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer { ...@@ -124,16 +120,9 @@ contract GasBenchMark_OptimismPortal is Portal_Initializer {
} }
contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer { contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {
uint128 internal INITIAL_BASE_FEE;
function setUp() public virtual override {
super.setUp();
INITIAL_BASE_FEE = op.INITIAL_BASE_FEE();
}
function test_sendMessage_benchmark_0() external { function test_sendMessage_benchmark_0() external {
vm.pauseGasMetering(); vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE); setPrevBaseFee(vm, address(op), 1 gwei);
// The amount of data typically sent during a bridge deposit. // The amount of data typically sent during a bridge deposit.
bytes bytes
memory data = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; memory data = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
...@@ -153,11 +142,8 @@ contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer { ...@@ -153,11 +142,8 @@ contract GasBenchMark_L1CrossDomainMessenger is Messenger_Initializer {
} }
contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer { contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
uint128 internal INITIAL_BASE_FEE;
function setUp() public virtual override { function setUp() public virtual override {
super.setUp(); super.setUp();
INITIAL_BASE_FEE = op.INITIAL_BASE_FEE();
deal(address(L1Token), alice, 100000, true); deal(address(L1Token), alice, 100000, true);
vm.startPrank(alice, alice); vm.startPrank(alice, alice);
L1Token.approve(address(L1Bridge), type(uint256).max); L1Token.approve(address(L1Bridge), type(uint256).max);
...@@ -165,7 +151,7 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer { ...@@ -165,7 +151,7 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
function test_depositETH_benchmark_0() external { function test_depositETH_benchmark_0() external {
vm.pauseGasMetering(); vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE); setPrevBaseFee(vm, address(op), 1 gwei);
vm.resumeGasMetering(); vm.resumeGasMetering();
L1Bridge.depositETH{ value: 500 }(50000, hex""); L1Bridge.depositETH{ value: 500 }(50000, hex"");
} }
...@@ -179,7 +165,7 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer { ...@@ -179,7 +165,7 @@ contract GasBenchMark_L1StandardBridge_Deposit is Bridge_Initializer {
function test_depositERC20_benchmark_0() external { function test_depositERC20_benchmark_0() external {
vm.pauseGasMetering(); vm.pauseGasMetering();
setPrevBaseFee(vm, address(op), INITIAL_BASE_FEE); setPrevBaseFee(vm, address(op), 1 gwei);
vm.resumeGasMetering(); vm.resumeGasMetering();
L1Bridge.bridgeERC20({ L1Bridge.bridgeERC20({
_localToken: address(L1Token), _localToken: address(L1Token),
......
...@@ -28,6 +28,7 @@ import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol"; ...@@ -28,6 +28,7 @@ import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol";
import { IL1ChugSplashDeployer } from "../legacy/L1ChugSplashProxy.sol"; import { IL1ChugSplashDeployer } from "../legacy/L1ChugSplashProxy.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { LegacyMintableERC20 } from "../legacy/LegacyMintableERC20.sol"; import { LegacyMintableERC20 } from "../legacy/LegacyMintableERC20.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
contract CommonTest is Test { contract CommonTest is Test {
address alice = address(128); address alice = address(128);
...@@ -158,6 +159,7 @@ contract Portal_Initializer is L2OutputOracle_Initializer { ...@@ -158,6 +159,7 @@ contract Portal_Initializer is L2OutputOracle_Initializer {
// Test target // Test target
OptimismPortal internal opImpl; OptimismPortal internal opImpl;
OptimismPortal internal op; OptimismPortal internal op;
SystemConfig systemConfig;
event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success); event WithdrawalFinalized(bytes32 indexed withdrawalHash, bool success);
event WithdrawalProven( event WithdrawalProven(
...@@ -169,7 +171,22 @@ contract Portal_Initializer is L2OutputOracle_Initializer { ...@@ -169,7 +171,22 @@ contract Portal_Initializer is L2OutputOracle_Initializer {
function setUp() public virtual override { function setUp() public virtual override {
super.setUp(); super.setUp();
opImpl = new OptimismPortal({ _l2Oracle: oracle, _guardian: guardian, _paused: true }); systemConfig = new SystemConfig({
_owner: address(0),
_overhead: 0,
_scalar: 10000,
_batcherHash: bytes32(0),
_gasLimit: 30_000_000,
_unsafeBlockSigner: address(0)
});
opImpl = new OptimismPortal({
_l2Oracle: oracle,
_guardian: guardian,
_paused: true,
_config: systemConfig
});
Proxy proxy = new Proxy(multisig); Proxy proxy = new Proxy(multisig);
vm.prank(multisig); vm.prank(multisig);
proxy.upgradeToAndCall( proxy.upgradeToAndCall(
......
...@@ -9,6 +9,7 @@ import { OptimismPortal } from "../L1/OptimismPortal.sol"; ...@@ -9,6 +9,7 @@ import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { Types } from "../libraries/Types.sol"; import { Types } from "../libraries/Types.sol";
import { Hashing } from "../libraries/Hashing.sol"; import { Hashing } from "../libraries/Hashing.sol";
import { Proxy } from "../universal/Proxy.sol"; import { Proxy } from "../universal/Proxy.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
contract OptimismPortal_Test is Portal_Initializer { contract OptimismPortal_Test is Portal_Initializer {
event Paused(address); event Paused(address);
...@@ -1045,10 +1046,12 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer { ...@@ -1045,10 +1046,12 @@ contract OptimismPortalUpgradeable_Test is Portal_Initializer {
} }
function test_params_initValuesOnProxy_succeeds() external { function test_params_initValuesOnProxy_succeeds() external {
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = OptimismPortal( OptimismPortal p = OptimismPortal(payable(address(proxy)));
payable(address(proxy))
).params(); (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = p.params();
assertEq(prevBaseFee, opImpl.INITIAL_BASE_FEE());
SystemConfig.ResourceConfig memory rcfg = p.resourceConfig();
assertEq(prevBaseFee, rcfg.minimumBaseFee);
assertEq(prevBoughtGas, 0); assertEq(prevBoughtGas, 0);
assertEq(prevBlockNum, initialBlockNum); assertEq(prevBlockNum, initialBlockNum);
} }
......
...@@ -3,6 +3,7 @@ pragma solidity 0.8.15; ...@@ -3,6 +3,7 @@ pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test } from "forge-std/Test.sol";
import { ResourceMetering } from "../L1/ResourceMetering.sol"; import { ResourceMetering } from "../L1/ResourceMetering.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
import { Proxy } from "../universal/Proxy.sol"; import { Proxy } from "../universal/Proxy.sol";
contract MeterUser is ResourceMetering { contract MeterUser is ResourceMetering {
...@@ -14,6 +15,18 @@ contract MeterUser is ResourceMetering { ...@@ -14,6 +15,18 @@ contract MeterUser is ResourceMetering {
__ResourceMetering_init(); __ResourceMetering_init();
} }
function resourceConfig() public override pure returns (SystemConfig.ResourceConfig memory) {
SystemConfig.ResourceConfig memory config = SystemConfig.ResourceConfig({
maxResourceLimit: 20_000_000,
elasticityMultiplier: 10,
baseFeeMaxChangeDenominator: 8,
minimumBaseFee: 1 gwei,
systemTxMaxGas: 1_000_000,
maximumBaseFee: type(uint128).max
});
return config;
}
function use(uint64 _amount) public metered(_amount) {} function use(uint64 _amount) public metered(_amount) {}
function set( function set(
...@@ -29,6 +42,11 @@ contract MeterUser is ResourceMetering { ...@@ -29,6 +42,11 @@ contract MeterUser is ResourceMetering {
} }
} }
/**
* @title ResourceConfig
* @notice The tests are based on the default config values. It is expected that
* the config values used in these tests are ran in production.
*/
contract ResourceMetering_Test is Test { contract ResourceMetering_Test is Test {
MeterUser internal meter; MeterUser internal meter;
uint64 initialBlockNum; uint64 initialBlockNum;
...@@ -38,42 +56,15 @@ contract ResourceMetering_Test is Test { ...@@ -38,42 +56,15 @@ contract ResourceMetering_Test is Test {
initialBlockNum = uint64(block.number); initialBlockNum = uint64(block.number);
} }
/**
* @notice The INITIAL_BASE_FEE must be less than the MAXIMUM_BASE_FEE
* and greater than the MINIMUM_BASE_FEE.
*/
function test_meter_initialBaseFee_succeeds() external {
uint256 max = uint256(meter.MAXIMUM_BASE_FEE());
uint256 min = uint256(meter.MINIMUM_BASE_FEE());
uint256 initial = uint256(meter.INITIAL_BASE_FEE());
assertTrue(max >= initial);
assertTrue(min <= initial);
}
/**
* @notice The MINIMUM_BASE_FEE must be less than the MAXIMUM_BASE_FEE.
*/
function test_meter_minBaseFeeLessThanMaxBaseFee_succeeds() external {
uint256 max = uint256(meter.MAXIMUM_BASE_FEE());
uint256 min = uint256(meter.MINIMUM_BASE_FEE());
assertTrue(max > min);
}
function test_meter_initialResourceParams_succeeds() external { function test_meter_initialResourceParams_succeeds() external {
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
SystemConfig.ResourceConfig memory rcfg = meter.resourceConfig();
assertEq(prevBaseFee, meter.INITIAL_BASE_FEE()); assertEq(prevBaseFee, rcfg.minimumBaseFee);
assertEq(prevBoughtGas, 0); assertEq(prevBoughtGas, 0);
assertEq(prevBlockNum, initialBlockNum); assertEq(prevBlockNum, initialBlockNum);
} }
function test_meter_maxValue_succeeds() external {
uint256 max = uint256(meter.MAX_RESOURCE_LIMIT());
uint256 target = uint256(meter.TARGET_RESOURCE_LIMIT());
uint256 elasticity = uint256(meter.ELASTICITY_MULTIPLIER());
assertEq(max / elasticity, target);
}
function test_meter_updateParamsNoChange_succeeds() external { function test_meter_updateParamsNoChange_succeeds() external {
meter.use(0); // equivalent to just updating the base fee and block number meter.use(0); // equivalent to just updating the base fee and block number
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
...@@ -116,8 +107,9 @@ contract ResourceMetering_Test is Test { ...@@ -116,8 +107,9 @@ contract ResourceMetering_Test is Test {
} }
function test_meter_updateNoGasDelta_succeeds() external { function test_meter_updateNoGasDelta_succeeds() external {
uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT())); SystemConfig.ResourceConfig memory rcfg = meter.resourceConfig();
meter.use(target); uint256 target = uint256(rcfg.maxResourceLimit) / uint256(rcfg.elasticityMultiplier);
meter.use(uint64(target));
(uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params(); (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum) = meter.params();
assertEq(prevBaseFee, 1000000000); assertEq(prevBaseFee, 1000000000);
...@@ -126,12 +118,14 @@ contract ResourceMetering_Test is Test { ...@@ -126,12 +118,14 @@ contract ResourceMetering_Test is Test {
} }
function test_meter_useMax_succeeds() external { function test_meter_useMax_succeeds() external {
uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT())); SystemConfig.ResourceConfig memory rcfg = meter.resourceConfig();
uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER())); uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);
meter.use(target * elasticity); uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);
meter.use(target * elasticityMultiplier);
(, uint64 prevBoughtGas, ) = meter.params(); (, uint64 prevBoughtGas, ) = meter.params();
assertEq(prevBoughtGas, target * elasticity); assertEq(prevBoughtGas, target * elasticityMultiplier);
vm.roll(initialBlockNum + 1); vm.roll(initialBlockNum + 1);
meter.use(0); meter.use(0);
...@@ -140,10 +134,12 @@ contract ResourceMetering_Test is Test { ...@@ -140,10 +134,12 @@ contract ResourceMetering_Test is Test {
} }
function test_meter_useMoreThanMax_reverts() external { function test_meter_useMoreThanMax_reverts() external {
uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT())); SystemConfig.ResourceConfig memory rcfg = meter.resourceConfig();
uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER())); uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);
uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);
vm.expectRevert("ResourceMetering: cannot buy more gas than available gas limit"); vm.expectRevert("ResourceMetering: cannot buy more gas than available gas limit");
meter.use(target * elasticity + 1); meter.use(target * elasticityMultiplier + 1);
} }
// Demonstrates that the resource metering arithmetic can tolerate very large gaps between // Demonstrates that the resource metering arithmetic can tolerate very large gaps between
...@@ -153,9 +149,11 @@ contract ResourceMetering_Test is Test { ...@@ -153,9 +149,11 @@ contract ResourceMetering_Test is Test {
// At 12 seconds per block, this number is effectively unreachable. // At 12 seconds per block, this number is effectively unreachable.
vm.assume(_blockDiff < 433576281058164217753225238677900874458691); vm.assume(_blockDiff < 433576281058164217753225238677900874458691);
uint64 target = uint64(uint256(meter.TARGET_RESOURCE_LIMIT())); SystemConfig.ResourceConfig memory rcfg = meter.resourceConfig();
uint64 elasticity = uint64(uint256(meter.ELASTICITY_MULTIPLIER())); uint64 target = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);
vm.assume(_amount < target * elasticity); uint64 elasticityMultiplier = uint64(rcfg.elasticityMultiplier);
vm.assume(_amount < target * elasticityMultiplier);
vm.roll(initialBlockNum + _blockDiff); vm.roll(initialBlockNum + _blockDiff);
meter.use(_amount); meter.use(_amount);
} }
...@@ -182,6 +180,18 @@ contract CustomMeterUser is ResourceMetering { ...@@ -182,6 +180,18 @@ contract CustomMeterUser is ResourceMetering {
}); });
} }
function resourceConfig() public override pure returns (SystemConfig.ResourceConfig memory) {
SystemConfig.ResourceConfig memory config = SystemConfig.ResourceConfig({
maxResourceLimit: 20_000_000,
elasticityMultiplier: 10,
baseFeeMaxChangeDenominator: 8,
minimumBaseFee: 1 gwei,
systemTxMaxGas: 1_000_000,
maximumBaseFee: type(uint128).max
});
return config;
}
function use(uint64 _amount) public returns (uint256) { function use(uint64 _amount) public returns (uint256) {
uint256 initialGas = gasleft(); uint256 initialGas = gasleft();
_metered(_amount, initialGas); _metered(_amount, initialGas);
...@@ -224,10 +234,11 @@ contract ArtifactResourceMetering_Test is Test { ...@@ -224,10 +234,11 @@ contract ArtifactResourceMetering_Test is Test {
vm.roll(1_000_000); vm.roll(1_000_000);
MeterUser base = new MeterUser(); MeterUser base = new MeterUser();
minimumBaseFee = uint128(uint256(base.MINIMUM_BASE_FEE())); SystemConfig.ResourceConfig memory rcfg = base.resourceConfig();
maximumBaseFee = uint128(uint256(base.MAXIMUM_BASE_FEE())); minimumBaseFee = uint128(rcfg.minimumBaseFee);
maxResourceLimit = uint64(uint256(base.MAX_RESOURCE_LIMIT())); maximumBaseFee = rcfg.maximumBaseFee;
targetResourceLimit = uint64(uint256(base.TARGET_RESOURCE_LIMIT())); maxResourceLimit = uint64(rcfg.maxResourceLimit);
targetResourceLimit = uint64(rcfg.maxResourceLimit) / uint64(rcfg.elasticityMultiplier);
outfile = string.concat(vm.projectRoot(), "/.resource-metering.csv"); outfile = string.concat(vm.projectRoot(), "/.resource-metering.csv");
try vm.removeFile(outfile) {} catch {} try vm.removeFile(outfile) {} catch {}
......
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