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

Holocene: contracts part for separating dynamic&static l1 attributes #11600

Conversation

blockchaindevsh
Copy link

This PR serves as a first step for "Separate Dynamic and Static L1 Attributes Values", it migrates existing SystemConfig updates to follow the pattern designed in ethereum-optimism/specs#122 .

@blockchaindevsh
Copy link
Author

blockchaindevsh commented Aug 26, 2024

The remaining test failure is here.

It seems the testcase itself is not sound:

  1. SystemConfig/OptimismPortal2 contracts are counted twice by _getNumInitializable() because of the existence of SystemConfigInterop/OptimismPortalInterop .
  2. OptimismSuperchainERC20 is not excluded by _getNumInitializable(), but the comment Omitting OptimismSuperchainERC20 due to using OZ v5 Initializable. indicates it should.
  3. The contracts variable includes DisputeGameFactory, but it's under dispute directory, not under L1/L2 directory(_getNumInitializable() only scans L1/L2).

Comment on lines 30 to 37
if (msg.sender != DEPOSITOR_ACCOUNT()) revert NotDepositor();

if (_type == ConfigType.SET_GAS_PAYING_TOKEN) {
_setGasPayingToken(_value);
} else if (_type == ConfigType.ADD_DEPENDENCY) {
_addDependency(_value);
} else if (_type == ConfigType.REMOVE_DEPENDENCY) {
_removeDependency(_value);
Copy link
Collaborator

Choose a reason for hiding this comment

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

not a solidity expert can/should you call "super.setConfig(_type, _value)" instead of duplicating this code here?

Copy link
Author

Choose a reason for hiding this comment

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

Note: L1BlockHolocene will be shipped before L1BlockInterop, and L1BlockInterop.setConfig is external instead of public, so not callable from inherited functions.

REMOVE_DEPENDENCY
REMOVE_DEPENDENCY,
SET_BATCHER_HASH,
SET_GAS_CONFIG_ECOTONE,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we replace this with two new config type events for each of the two values we hacked into the gas config with Ecotone? E.g.

SET_BASE_FEE_SCALAR
SET_BLOB_BASE_FEE_SCALAR

...allowing each to be updated independently.

Copy link
Contributor

Choose a reason for hiding this comment

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

I am on board with this if you think that it results in less operational overhead, this just means a multicall is necessary to set both

Copy link
Collaborator

Choose a reason for hiding this comment

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

Alternatively just have a SET_FEE_SCALARS for both ... Important thing is to get away from the Ecotone hack that combined both fee scalars into the single "scalar" L1 attribute.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Personally I don't think it's worth having two ways to do the same thing. Probably it's best to follow Mark's advice of starting with a specification where we can argue over these API details before turning it into code?

@@ -387,7 +387,7 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
/// @notice Internal function for updating the fee scalars as of the Ecotone upgrade.
/// @param _basefeeScalar New basefeeScalar value.
/// @param _blobbasefeeScalar New blobbasefeeScalar value.
function _setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) internal {
function _setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) internal virtual {
Copy link
Collaborator

Choose a reason for hiding this comment

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

If we separate out the gasconfig into two update types like I suggested, we can deprecate setGasConfigEcotone entirely. (Of course we have make sure this one works if someone calls it, so we'll still have to override this implementation in SystemConfigHolocene.)

Copy link
Collaborator

@roberto-bayardo roberto-bayardo Aug 26, 2024

Choose a reason for hiding this comment

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

Oh and you'll also want to change "_setGasConfig" to virtual so we can override it to make it do the right thing. Though since setGasConfig() has been deprecated since Ecotone, you might also just remove _setGasConfig() entirely, then make setGasConfig() revert, with the error indicating to use set(Blob)BasefeeScalar() instead.

Copy link
Collaborator

@roberto-bayardo roberto-bayardo Aug 27, 2024

Choose a reason for hiding this comment

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

Correction to my statement above, setGasConfig() was actually not deprecated until after Ecotone (Ecotone didn't involve any changes to L1 contracts, which is why we had to hack in the new behavior using the old API). The setGasConfigEcotone() was added in a later update of the L1 contracts. IMO it should have been named setFeeScalars() -- I don't think hardfork names should be in public APIs if not entirely necessary. Regardless, since setGasConfig() wasn't deprecated until later, probably we want to keep it working for a bit longer rather than removing it entirely or just making it revert. Its implementation of course can just be made to call the new contract function(s) after appropriately parsing out the values.

/// @notice Internal function for updating the fee scalars as of the Ecotone upgrade.
/// @param _basefeeScalar New basefeeScalar value.
/// @param _blobbasefeeScalar New blobbasefeeScalar value.
function _setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) internal override {
Copy link
Collaborator

@roberto-bayardo roberto-bayardo Aug 26, 2024

Choose a reason for hiding this comment

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

Implementation here could just be:

_setBasefeeScalar(_basefeeScalar);
_setBlobBasefeeScalar(_blobBasefeeScalar);


/// @notice Internal method to set new gas config.
/// @param _value The encoded value with which to set the new batcher hash.
function _setGasConfigEcotone(bytes calldata _value) internal {
Copy link
Collaborator

Choose a reason for hiding this comment

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

drop, replace with _setBasefeeScalar() and _setBlobBasefeeScalar()

event BatcherHashSet(bytes32 indexed batcherHash);

/// @notice Event emitted when a new ecotone gas config is set.
event GasConfigEcotoneSet(uint32 indexed blobBaseFeeScalar, uint32 indexed baseFeeScalar);
Copy link
Collaborator

@roberto-bayardo roberto-bayardo Aug 26, 2024

Choose a reason for hiding this comment

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

replace w/ BasefeeScalarSet and BlobBasefeeScalarSet.

(nit: Note that "Basefee" and "basefee" are the idiomatic casings, whereas "BaseFee" and "baseFee" are not.)

Copy link
Author

Choose a reason for hiding this comment

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

I changed the naming convention to the idiomatic casings for the new code, but didn't change the existing naming convention in the old code, e.g.,

uint32 public blobBaseFeeScalar;
and
uint32 public baseFeeScalar;
, since it may break things. We can do it in the future.

@roberto-bayardo
Copy link
Collaborator

Summarizing most of my comments above:

I think we should use this change as an opportunity to undo the ugly Ecotone gas config hack where we smash basefeeScalar and blobBasefeeScalar into a single value.

For SystemConfigHolocene.sol, suggest adding:

setBasefeeSalar()
setBlobBasefeeScalar()

For SystemConfig.sol, deprecate:

setGasConfig (make it revert, or make it virtual so we can override it to make it do the right thing if it still gets called.
setGasConfigEcotone (make it virtual, then Holocene implementation will just call the two new methods above).

/// @custom:predeploy 0x4200000000000000000000000000000000000015
/// @title L1BlockHolocene
/// @notice Interop extenstions of L1Block.
contract L1BlockHolocene is L1BlockInterop {
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't want to target L1BlockInterop here since this will go to production before interop. I think naming this L1BlockHolocene for now is safer, even though I think this could technically go right into the L1Block contract itself. By not putting this logic into L1Block now, it reduces risk that somebody deploys with it before its ready end to end, we will need to pull it into the regular L1Block contract in the future.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Mark, should we also be modifying SystemConfig.sol directly rather than introducing a SystemConfigHolocene.sol?

Copy link
Author

@blockchaindevsh blockchaindevsh Aug 27, 2024

Choose a reason for hiding this comment

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

Good catch, fixed in 4618303 .

/// 4. _basefee L1 base fee.
/// 5. _blobBaseFee L1 blob base fee.
/// 6. _hash L1 blockhash.
function setL1BlockValuesHolocene() external {
Copy link
Contributor

Choose a reason for hiding this comment

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

We will want to implement the following comment as setL1BlockValuesHolocene: ethereum-optimism/specs#122 (comment)

Copy link
Author

Choose a reason for hiding this comment

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

Done in 4618303

@tynes
Copy link
Contributor

tynes commented Aug 26, 2024

This is great work so far, ultimately we will want a more formal spec before we can merge this to ensure that multi client implementations go easily and also its good for auditors to catch bugs. You can find an example of a similar sort of change here where the L1 attributes was modified for the ecotone hardfork

You can see an example of the SystemConfig setter spec here or here

@roberto-bayardo
Copy link
Collaborator

@blockchaindevsh I shared the above API discussion & background in the #hf-holocene discord to see if others have strong preferences.

@blockchaindevsh
Copy link
Author

blockchaindevsh commented Aug 27, 2024

@tynes @roberto-bayardo The latest commit still keeps changes in the XXXHolocene file(SystemConfigHolocene.sol/L1BlockHolocene.sol), and retains only setFeeScalars for setting fee scalars, the remaining issue to address is: should we pack basefeeScalar/blobBasefeeScalar into a single scalar as per the previous hack?

@tynes
Copy link
Contributor

tynes commented Aug 27, 2024

Usually we have this level of conversation at the specs level rather than the implementation so that code review is more checking specs against code.

We would want to get weigh in from other people like @roberto-bayardo @protolambda @sebastianst @geoknee


/// @notice Internal method to decode blobBaseFeeScalar and baseFeeScalar.
/// @return Decoded blobBaseFeeScalar and baseFeeScalar.
function _decodeScalar(uint256 _scalar) internal pure returns (uint32, uint32) {
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 will want encode/decode logic in a library so it can be a single source of truth and then imported everywhere that it is required so we only implement the logic once and we can unit test roundtrip

Copy link
Author

@blockchaindevsh blockchaindevsh Aug 28, 2024

Choose a reason for hiding this comment

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

Good point, the packing/unpacking logic is now moved into the library as packScalar/unpackScalar in this commit: e876fe4 . StaticConfig.encodeXXX returns bytes, while we need to maintain the scalar variable as uint256. This is the primary reason it was not encapsulated within the StaticConfig library.

@BlocksOnAChain BlocksOnAChain changed the title contracts part for separating dynamic&static l1 attributes Holocene: contracts part for separating dynamic&static l1 attributes Aug 28, 2024
Copy link
Contributor

This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 5 days.

@github-actions github-actions bot added the Stale label Sep 12, 2024
@tynes tynes closed this Sep 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants