Skip to content

Commit

Permalink
contracts-bedrock: fix StaticConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
0xfuturistic committed May 20, 2024
1 parent a889647 commit ed3823b
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 88 deletions.
8 changes: 2 additions & 6 deletions packages/contracts-bedrock/src/L2/L1Block.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ pragma solidity 0.8.15;
import { ISemver } from "src/universal/ISemver.sol";
import { Constants } from "src/libraries/Constants.sol";
import { GasPayingToken, IGasToken } from "src/libraries/GasPayingToken.sol";
import "src/libraries/L1BlockErrors.sol";
import "src/libraries/L1BlockEvents.sol";

/// @custom:proxied
/// @custom:predeploy 0x4200000000000000000000000000000000000015
Expand All @@ -13,12 +15,6 @@ import { GasPayingToken, IGasToken } from "src/libraries/GasPayingToken.sol";
/// set by the "depositor" account, a special system address. Depositor account transactions
/// are created by the protocol whenever we move to a new epoch.
contract L1Block is ISemver, IGasToken {
/// @notice Error returns when a non-depositor account tries to set L1 block values.
error NotDepositor();

/// @notice Event emitted when the gas paying token is set.
event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol);

/// @notice Address of the special depositor account.
function DEPOSITOR_ACCOUNT() public pure returns (address addr_) {
addr_ = Constants.DEPOSITOR_ACCOUNT;
Expand Down
144 changes: 62 additions & 82 deletions packages/contracts-bedrock/src/L2/L1BlockInterop.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,108 +2,88 @@
pragma solidity 0.8.15;

import { L1Block } from "src/L2/L1Block.sol";
import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import { GasPayingToken } from "src/libraries/GasPayingToken.sol";
import { StaticConfig } from "src/libraries/StaticConfig.sol";

/// @notice Thrown when a non-depositor account attempts to set L1 block values.
error NotDepositor();

/// @notice Thrown when dependencySetSize does not match the length of the dependency set.
error DependencySetSizeMismatch();
/// @notice Enum representing different types of configurations that can be set on L1Block.
/// @custom:value GAS_PAYING_TOKEN Represents the config type for the gas paying token.
/// @custom:value ADD_DEPENDENCY Represents the config type for adding a chain to the interchain dependency set.
/// @custom:value REMOVE_DEPENDENCY Represents the config type for removing a chain from the interchain dependency set.
enum ConfigType {
GAS_PAYING_TOKEN,
ADD_DEPENDENCY,
REMOVE_DEPENDENCY
}

/// @custom:proxied
/// @custom:predeploy 0x4200000000000000000000000000000000000015
/// @title L1BlockInterop
/// @notice Interop extenstions of L1Block.
contract L1BlockInterop is L1Block {
/// @notice The chain IDs of the interop dependency set.
uint256[] public dependencySet;
using EnumerableSet for EnumerableSet.UintSet;

/// @custom:semver 1.3.0+interop
/// @notice The interop dependency set, containing the chain IDs in it.
EnumerableSet.UintSet public dependencySet;

/// @custom:semver 1.4.0+interop
function version() public pure override returns (string memory) {
return string.concat(super.version(), "+interop");
}

/// @notice Updates the L1 block values for an Interop upgraded chain.
/// Params are packed and passed in as raw msg.data instead of ABI to reduce calldata size.
/// Params are expected to be in the following order:
/// 1. _baseFeeScalar L1 base fee scalar
/// 2. _blobBaseFeeScalar L1 blob base fee scalar
/// 3. _sequenceNumber Number of L2 blocks since epoch start.
/// 4. _timestamp L1 timestamp.
/// 5. _number L1 blocknumber.
/// 6. _basefee L1 base fee.
/// 7. _blobBaseFee L1 blob base fee.
/// 8. _hash L1 blockhash.
/// 9. _batcherHash Versioned hash to authenticate batcher by.
/// 10. _dependencySetSize Size of the interop dependency set.
/// 11. _dependencySet Array of chain IDs for the interop dependency set.
function setL1BlockValuesInterop() external {
address depositor = DEPOSITOR_ACCOUNT();
assembly {
// Revert if the caller is not the depositor account.
if xor(caller(), depositor) {
mstore(0x00, 0x3cc50b45) // 0x3cc50b45 is the 4-byte selector of "NotDepositor()"
revert(0x1C, 0x04) // returns the stored 4-byte selector from above
}
// sequencenum (uint64), blobBaseFeeScalar (uint32), baseFeeScalar (uint32)
sstore(sequenceNumber.slot, shr(128, calldataload(4)))
// number (uint64) and timestamp (uint64)
sstore(number.slot, shr(128, calldataload(20)))
sstore(basefee.slot, calldataload(36)) // uint256
sstore(blobBaseFee.slot, calldataload(68)) // uint256
sstore(hash.slot, calldataload(100)) // bytes32
sstore(batcherHash.slot, calldataload(132)) // bytes32

// Load dependencySetSize from calldata (at offset 164 after calldata for setL1BlockValuesEcotone ends)
let dependencySetSize_ := shr(248, calldataload(164))

// Revert if dependencySetSize_ doesn't match the length of dependencySet in calldata
if xor(add(165, mul(dependencySetSize_, 0x20)), calldatasize()) {
mstore(0x00, 0x44165b6a) // 0x44165b6a is the 4-byte selector of "DependencySetSizeMismatch()"
revert(0x1C, 0x04) // returns the stored 4-byte selector from above
}

// Use memory to hash and get the start index of dependencySet
mstore(0x00, dependencySet.slot)
let dependencySetStartIndex := keccak256(0x00, 0x20)

// Iterate over calldata dependencySet and write to store dependencySet
for { let i := 0 } lt(i, dependencySetSize_) { i := add(i, 1) } {
// Load value from calldata and write to storage (dependencySet) at index
let val := calldataload(add(165, mul(i, 0x20)))
sstore(add(dependencySetStartIndex, i), val)
}

// Update length of dependencySet array
sstore(dependencySet.slot, dependencySetSize_)
}
}

/// @notice Returns true if a chain ID is in the interop dependency set and false otherwise.
/// Every chain ID is in the interop dependency set of itself.
/// The chain's chain ID is always considered to be in the dependency set.
/// @param _chainId The chain ID to check.
/// @return True if the chain ID to check is in the interop dependency set. False otherwise.
function isInDependencySet(uint256 _chainId) public view returns (bool) {
// Every chain ID is in the interop dependency set of itself.
if (_chainId == block.chainid) {
return true;
}

uint256 length = dependencySet.length;
for (uint256 i = 0; i < length;) {
if (dependencySet[i] == _chainId) {
return true;
}
unchecked {
i++;
}
}

return false;
return _chainId == block.chainid || dependencySet.contains(_chainId);
}

/// @notice Returns the size of the interop dependency set.
/// @return The size of the interop dependency set.
function dependencySetSize() external view returns (uint8) {
return uint8(dependencySet.length);
return uint8(dependencySet.length());
}

/// @notice Sets static configuration options for the L2 system. Can only be called by the special
/// depositor account.
/// @param _type The type of configuration to set.
/// @param _value The encoded value with which to set the configuration.
function setConfig(ConfigType _type, bytes calldata _value) external {
if (msg.sender != DEPOSITOR_ACCOUNT()) revert NotDepositor();

// For GAS_PAYING_TOKEN config type
if (_type == ConfigType.GAS_PAYING_TOKEN) {
(address token, uint8 decimals, bytes32 name, bytes32 symbol) = StaticConfig.decodeGasPayingToken(_value);

GasPayingToken.set({ _token: token, _decimals: decimals, _name: name, _symbol: symbol });

emit GasPayingTokenSet({ token: token, decimals: decimals, name: name, symbol: symbol });
return;
}

// For ADD_DEPENDENCY config type
if (_type == ConfigType.ADD_DEPENDENCY) {
uint256 chainId = StaticConfig.decodeAddDependency(_value);

if (dependencySet.length() == type(uint8).max) revert DependencySetSizeTooLarge();

dependencySet.add(chainId);

emit DependencyAdded(chainId);
return;
}

// For REMOVE_DEPENDENCY config type
if (_type == ConfigType.REMOVE_DEPENDENCY) {
uint256 chainId = StaticConfig.decodeRemoveDependency(_value);

if (chainId == block.chainid) revert CantRemovedChainId();

if (!dependencySet.remove(chainId)) revert NotDependency();

emit DependencyRemoved(chainId);
return;
}
}
}
14 changes: 14 additions & 0 deletions packages/contracts-bedrock/src/libraries/L1BlockErrors.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

/// @notice Error returns when a non-depositor account tries to set L1 block values.
error NotDepositor();

/// @notice Error when a chain ID is not in the interop dependency set.
error NotDependency();

/// @notice Error when the interop dependency set size is too large.
error DependencySetSizeTooLarge();

/// @notice Error when the chain's chain ID is attempted to be removed from the interop dependency set.
error CantRemovedChainId();
11 changes: 11 additions & 0 deletions packages/contracts-bedrock/src/libraries/L1BlockEvents.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

/// @notice Event emitted when the gas paying token is set.
event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol);

/// @notice Event emitted when a new dependency is added to the interop dependency set.
event DependencyAdded(uint256 indexed chainId);

/// @notice Event emitted when a dependency is removed from the interop dependency set.
event DependencyRemoved(uint256 indexed chainId);

0 comments on commit ed3823b

Please sign in to comment.