Система реєстрації екземплярів (Instance Registry Pattern) використовує центральний смарт-контракт (реєстр) для управління адресами інших розгорнутих контрактів. Це схоже на версію DNS для смарт-контрактів: замість того, щоб запам’ятовувати складні адреси, ви просто запитуєте ім’я і отримуєте необхідну адресу. Це спрощує керування контрактами та забезпечує зручний доступ до потрібних адрес без необхідності хардкодити значення в коді.
Використання цієї системи дозволяє оновлювати адреси контрактів без потреби перерозгортання всього проєкту. Крім того, інші контракти можуть динамічно знаходити залежності, що особливо важливо для великих проєктів із складною архітектурою.
Простий приклад реалізації реєстру на Solidity:
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
contract Registry {
mapping(bytes32 => address) public contracts;
function setContract(bytes32 name, address _address) external {
contracts[name] = _address;
}
function getContract(bytes32 name) external view returns (address) {
return contracts[name];
}
}
У цьому прикладі ви можете зареєструвати адресу контракту з ім’ям (наприклад, "UserStorage"
) і отримати її пізніше, що є дуже корисним для модульних систем.
Щоб підвищити безпеку, ми додаємо можливість авторизації для зміни записів у реєстрі. Для цього використовуються:
Ownable
від OpenZeppelin для обмеження адміністративних дій.modifier
, щоб дозволити тільки авторизованим контрактам змінювати записи.- Події для забезпечення прозорості та аудиту змін.
Ось повний код з додаванням безпеки та подій:
solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Registry is Ownable {
mapping(bytes32 => address) private contracts;
mapping(address => bool) private authorizedCallers;
event ContractSet(bytes32 indexed name, address indexed newAddress);
event CallerAuthorized(address indexed caller, bool authorized);
modifier onlyAuthorized() {
require(authorizedCallers[msg.sender], "Not an authorized caller");
_;
}
function authorizeCaller(address caller, bool _authorized) external onlyOwner {
authorizedCallers[caller] = authorized;
emit CallerAuthorized(caller, _authorized);
}
function setContract(bytes32 name, address _address) external onlyAuthorized {
contracts[name] = address;
emit ContractSet(name, _address);
}
function getContract(bytes32 name) external view returns (address) {
return contracts[name];
}
}
Це дозволяє контролювати, хто може вносити зміни до реєстру, забезпечуючи безпечний доступ до смарт-контрактів. Усі зміни та оновлення зберігаються в подіях, що дозволяє легко відслідковувати історію змін через блок-експлорери або підграфи.
Система реєстрації екземплярів — це потужний інструмент для розробки масштабованих та безпечних смарт-контрактів. Вона допомагає спростити керування контрактами та забезпечує зручний доступ до потрібних ресурсів, зберігаючи при цьому високу безпеку та прозорість.
Перекладено з: Design Patterns — vamos organizar para deixar tudo bonitinho?