L1LineaTokenBurner

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/interfaces/IGenericErrors.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.30;

/**
 * @title Interface declaring generic errors.
 * @author ConsenSys Software Inc.
 * @custom:security-contact security-report@linea.build
 */
interface IGenericErrors {
  /**
   * @dev Thrown when a parameter is the zero address.
   */
  error ZeroAddressNotAllowed();

  /**
   * @dev Thrown when a parameter is the zero hash.
   */
  error ZeroHashNotAllowed();
}
"
    },
    "src/messaging/l1/interfaces/IL1MessageManager.sol": {
      "content": "// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.30;

/**
 * @title L1 Message manager interface for current functions, events and errors.
 * @author ConsenSys Software Inc.
 * @custom:security-contact security-report@linea.build
 */
interface IL1MessageManager {
  /**
   * @notice Emitted when a new message is sent and the rolling hash updated.
   * @param messageNumber The unique indexed message number for the message.
   * @param rollingHash The indexed rolling hash computed for the current message number.
   * @param messageHash The indexed hash of the message parameters.
   */
  event RollingHashUpdated(uint256 indexed messageNumber, bytes32 indexed rollingHash, bytes32 indexed messageHash);

  /**
   * @notice Emitted when the L2 Merkle root has been anchored on L1.
   * @param l2MerkleRoot The indexed L2 Merkle root that has been anchored on L1 Ethereum.
   * @param treeDepth The indexed tree depth of the Merkle root.
   * @dev There may be more than one of these in a finalization depending on the amount of L2->L1 messages in the finalization.
   */
  event L2MerkleRootAdded(bytes32 indexed l2MerkleRoot, uint256 indexed treeDepth);

  /**
   * @notice Emitted when the L2 block contains L2 messages during finalization.
   * @param l2Block The indexed L2 block containing L2 to L1 messages.
   * @dev This is used externally in the logic for determining which messages belong to which Merkle root when claiming.
   */
  event L2MessagingBlockAnchored(uint256 indexed l2Block);

  /**
   * @dev Thrown when the message has already been claimed.
   */
  error MessageAlreadyClaimed(uint256 messageIndex);

  /**
   * @dev Thrown when the L2 Merkle root has already been anchored on L1.
   */
  error L2MerkleRootAlreadyAnchored(bytes32 merkleRoot);

  /**
   * @dev Thrown when the L2 messaging blocks offsets bytes length is not a multiple of 2.
   */
  error BytesLengthNotMultipleOfTwo(uint256 bytesLength);

  /**
   * @notice Checks if the L2->L1 message is claimed or not.
   * @param _messageNumber The message number on L2.
   * @return isClaimed Returns whether or not the message with _messageNumber has been claimed.
   */
  function isMessageClaimed(uint256 _messageNumber) external view returns (bool isClaimed);
}
"
    },
    "src/messaging/l1/interfaces/IL1MessageService.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.30;

/**
 * @title L1 Message Service interface for pre-existing functions, events, structs and errors.
 * @author ConsenSys Software Inc.
 * @custom:security-contact security-report@linea.build
 */

interface IL1MessageService {
  /**
   * @param proof The Merkle proof array related to the claimed message.
   * @param messageNumber The message number of the claimed message.
   * @param leafIndex The leaf index related to the Merkle proof of the message.
   * @param from The address of the original sender.
   * @param to The address the message is intended for.
   * @param fee The fee being paid for the message delivery.
   * @param value The value to be transferred to the destination address.
   * @param feeRecipient The recipient for the fee.
   * @param merkleRoot The Merkle root of the claimed message.
   * @param data The calldata to pass to the recipient.
   */
  struct ClaimMessageWithProofParams {
    bytes32[] proof;
    uint256 messageNumber;
    uint32 leafIndex;
    address from;
    address to;
    uint256 fee;
    uint256 value;
    address payable feeRecipient;
    bytes32 merkleRoot;
    bytes data;
  }

  /**
   * @dev Thrown when L2 Merkle root does not exist.
   */
  error L2MerkleRootDoesNotExist();

  /**
   * @dev Thrown when the Merkle proof is invalid.
   */
  error InvalidMerkleProof();

  /**
   * @dev Thrown when Merkle depth doesn't match proof length.
   */
  error ProofLengthDifferentThanMerkleDepth(uint256 actual, uint256 expected);

  /**
   * @notice Claims and delivers a cross-chain message using a Merkle proof.
   * @dev if tree depth is empty, it will revert with L2MerkleRootDoesNotExist.
   * @dev if tree depth is different than proof size, it will revert with ProofLengthDifferentThanMerkleDepth.
   * @param _params Collection of claim data with proof and supporting data.
   */
  function claimMessageWithProof(ClaimMessageWithProofParams calldata _params) external;
}
"
    },
    "src/operational/interfaces/IL1LineaToken.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0 OR MIT
pragma solidity 0.8.30;

/**
 * @title Simplified L1 Linea Token Interface.
 * @author Consensys Software Inc.
 * @custom:security-contact security-report@linea.build
 */
interface IL1LineaToken {
  /**
   * @dev Destroys `amount` tokens from the caller.
   * @param amount The amount of tokens to burn.
   */
  function burn(uint256 amount) external;

  /**
   * @dev Returns the amount of tokens owned by `account`.
   * @param account The address of the account to query.
   * @return The amount of tokens owned by `account`.
   */
  function balanceOf(address account) external view returns (uint256);
}
"
    },
    "src/operational/interfaces/IL1LineaTokenBurner.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0 OR MIT
pragma solidity 0.8.30;

import { IL1MessageService } from "../../messaging/l1/interfaces/IL1MessageService.sol";

/**
 * @title Interface for the L1 Linea Token Burner Contract.
 * @author Consensys Software Inc.
 * @custom:security-contact security-report@linea.build
 */
interface IL1LineaTokenBurner {
  /**
   * @notice Error thrown when there are no tokens to burn.
   */
  error NoTokensToBurn();

  /**
   * @notice Emitted when the L1 Linea Token Burner is initialized.
   * @param messageService The address of the Message Service contract.
   * @param lineaToken The address of the LINEA token contract.
   */
  event L1LineaTokenBurnerInitialized(address messageService, address lineaToken);

  /**
   * @notice Claims a message with proof and burns the LINEA tokens held by this contract.
   * @param _params The parameters required to claim the message with proof.
   */
  function claimMessageWithProof(IL1MessageService.ClaimMessageWithProofParams calldata _params) external;
}
"
    },
    "src/operational/L1LineaTokenBurner.sol": {
      "content": "// SPDX-License-Identifier: Apache-2.0 OR MIT
pragma solidity 0.8.30;

import { IL1LineaTokenBurner } from "./interfaces/IL1LineaTokenBurner.sol";
import { IL1MessageService } from "../messaging/l1/interfaces/IL1MessageService.sol";
import { IL1MessageManager } from "../messaging/l1/interfaces/IL1MessageManager.sol";
import { IGenericErrors } from "../interfaces/IGenericErrors.sol";
import { IL1LineaToken } from "./interfaces/IL1LineaToken.sol";

/**
 * @title L1 Linea Token Burner Contract.
 * @author Consensys Software Inc.
 * @custom:security-contact security-report@linea.build
 */
contract L1LineaTokenBurner is IL1LineaTokenBurner, IGenericErrors {
  /// @notice Address of the LINEA token contract
  address public immutable LINEA_TOKEN;
  /// @notice Address of the MessageService contract
  address public immutable MESSAGE_SERVICE;

  constructor(address _messageService, address _lineaToken) {
    require(_messageService != address(0), ZeroAddressNotAllowed());
    require(_lineaToken != address(0), ZeroAddressNotAllowed());

    MESSAGE_SERVICE = _messageService;
    LINEA_TOKEN = _lineaToken;

    emit L1LineaTokenBurnerInitialized(_messageService, _lineaToken);
  }

  /**
   * @notice Claims a message with proof and burns the LINEA tokens held by this contract.
   * @dev This is expected to be permissionless, allowing anyone to trigger the burn.
   * @param _params The parameters required to claim the message with proof.
   */
  function claimMessageWithProof(IL1MessageService.ClaimMessageWithProofParams calldata _params) external {
    if (!IL1MessageManager(MESSAGE_SERVICE).isMessageClaimed(_params.messageNumber)) {
      IL1MessageService(MESSAGE_SERVICE).claimMessageWithProof(_params);
    }

    uint256 balance = IL1LineaToken(LINEA_TOKEN).balanceOf(address(this));
    require(balance > 0, NoTokensToBurn());

    IL1LineaToken(LINEA_TOKEN).burn(balance);
  }
}
"
    }
  },
  "settings": {
    "viaIR": false,
    "optimizer": {
      "enabled": true,
      "runs": 10000
    },
    "evmVersion": "prague",
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}}

Tags:
Factory|addr:0x5ad9369254f29b724d98f6ce98cb7bad729969f3|verified:true|block:23698191|tx:0x44940f63f14c13c6dd194f0dcdce8b3af8de5e872a353dec5f344281ca7447ef|first_check:1761927618

Submitted on: 2025-10-31 17:20:18

Comments

Log in to comment.

No comments yet.