github.com/klaytn/klaytn@v1.12.1/contracts/system_contracts/registry/Registry.sol (about)

     1  // Copyright 2023 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // SPDX-License-Identifier: LGPL-3.0-only
    18  pragma solidity ^0.8.0;
    19  
    20  import "./IRegistry.sol";
    21  
    22  /**
    23   * @dev Registry is a contract that manages the addresses of system contracts.
    24   * Note: The pre-deployed system contracts will be directly injected into the registry in HF block.
    25   *
    26   * register: Registers a new system contract.
    27   *    - Only can be registered by governance.
    28   *    - If predecessor is not yet active, overwrite it.
    29   *
    30   * Code organization
    31   *    - Modifiers
    32   *    - Mutators
    33   *    - Getters
    34   */
    35  contract Registry is IRegistry {
    36      /* ========== MODIFIERS ========== */
    37      // /**
    38      //  * @dev Throws if not called by systemTx.
    39      //  * TODO: Decide whether to use this modifier or not.
    40      //  */
    41      // modifier onlySystemTx() {
    42      //     _;
    43      // }
    44  
    45      /**
    46       * @dev Throws if called by any account other than the owner.
    47       */
    48      modifier onlyOwner() {
    49          require(msg.sender == owner(), "Not owner");
    50          _;
    51      }
    52  
    53      /**
    54       * @dev Throws if the given string is empty.
    55       */
    56      modifier notEmptyString(string memory name) {
    57          bytes memory b = abi.encodePacked(name);
    58          require(b.length != 0, "Empty string");
    59          _;
    60      }
    61  
    62      /* ========== MUTATORS ========== */
    63      /**
    64       * @dev Registers a new system contract to the records.
    65       * @param name The name of the contract to register.
    66       * @param addr The address of the contract to register.
    67       * @param activation The activation block number of the contract.
    68       * NOTE: Register a zero address if you want to deprecate the contract without replacing it.
    69       */
    70      function register(
    71          string memory name,
    72          address addr,
    73          uint256 activation
    74      ) external override onlyOwner notEmptyString(name) {
    75          // Don't allow the current block since it affects to other txs in the same block.
    76          require(activation > block.number, "Can't register contract from past");
    77  
    78          uint256 length = records[name].length;
    79  
    80          if (length == 0) {
    81              names.push(name);
    82              records[name].push(Record(addr, activation));
    83          } else {
    84              Record storage last = records[name][length - 1];
    85              if (last.activation <= block.number) {
    86                  // Last record is active. Append new record.
    87                  records[name].push(Record(addr, activation));
    88              } else {
    89                  // Last record is not yet active. Overwrite last record.
    90                  last.addr = addr;
    91                  last.activation = activation;
    92              }
    93          }
    94  
    95          emit Registered(name, addr, activation);
    96      }
    97  
    98      /**
    99       * @dev Transfers ownership of the contract to a newOwner.
   100       * @param newOwner The address to transfer ownership to.
   101       */
   102      function transferOwnership(address newOwner) external override onlyOwner {
   103          require(newOwner != address(0), "Zero address");
   104          _owner = newOwner;
   105  
   106          emit OwnershipTransferred(msg.sender, newOwner);
   107      }
   108  
   109      /* ========== GETTERS ========== */
   110      /**
   111       * @dev Returns the address of contract if active at current block.
   112       * @param name The name of the contract to check.
   113       * Note: If there is no active contract, it returns address(0).
   114       */
   115      function getActiveAddr(string memory name) public view virtual override returns (address) {
   116          uint256 length = records[name].length;
   117  
   118          // activation is always in ascending order.
   119          for (uint256 i = length; i > 0; i--) {
   120              if (records[name][i - 1].activation <= block.number) {
   121                  return records[name][i - 1].addr;
   122              }
   123          }
   124  
   125          return address(0);
   126      }
   127  
   128      /**
   129       * @dev Returns all contract with same name.
   130       * @param name The name of the contract to check.
   131       */
   132      function getAllRecords(string memory name) public view override returns (Record[] memory) {
   133          return records[name];
   134      }
   135  
   136      /**
   137       * @dev Returns the all system contract names. (include deprecated contracts)
   138       */
   139      function getAllNames() public view override returns (string[] memory) {
   140          return names;
   141      }
   142  
   143      /**
   144       * @dev Returns the owner of the contract.
   145       */
   146      function owner() public view override returns (address) {
   147          return _owner;
   148      }
   149  }