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 }