diff --git a/.clinerules/basics.md b/.clinerules/basics.md new file mode 100644 index 000000000..f01299eb9 --- /dev/null +++ b/.clinerules/basics.md @@ -0,0 +1,15 @@ +# Guidelines + +## FUNDAMENTALS + - Never disobey these rules + - Do not ever read or manipulate the `.env` file or any file that matches the `*.env*` regex pattern + - Always ask permission before installing a new package + - Always ask permission before running a command directly on the console + +## GUIDELINES + - Update relevant documentation in the "/docs" folder as needed when modifying code + - Keep `.README` up to date with new capabilities + - Always add any generated files to `src/generated`, create this folder if it does not exist + + ## TESTING STANDARDS + - Always create unit tests for business logic added \ No newline at end of file diff --git a/docs/architecture.md b/docs/architecture.md index 1eebd9867..5d6466ceb 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -41,7 +41,7 @@ Every domain registered has to settle on this contract with its crucial data (ab ### Key responsibilities - Serves as the last step of a domain registration process by saving the domain data in its storage - Official final reference of an existence of a certain domain - we call `ZNSRegistry` to verify that a new domain being minted has not been minted already -- Is the first step in domain source discovery - we call `ZNSRegistry.getDomainResolver()` to find the Resolver that will tell us what this domain was created for (contract or wallet address, string, metadata hash, etc.). Currently ONLY `ZNSAddressResolver` is implemented, but more resolvers to come in the future for more data types. +- Is the first step in domain source discovery - we call `ZNSRegistry.getDomainResolver()` to find the Resolver that will tell us what this domain was created for (contract or wallet address, string, metadata hash, etc.). Currently `ZNSAddressResolver` and `ZNSStringResolver` are implemented, and additional resolvers can be added by admins via the Registry’s resolver-type mapping (`addResolverType`/`deleteResolverType`). - Reference for crucial domain related data (owner, resolver). - Provide a way to install operators for any owner to allow them access to changing resolvers without the presence of the owner @@ -53,7 +53,7 @@ A single token contract (ERC-721) responsible for tokenizing every domain/subdom - Mint a new token every time a domain is registered atomically within the register transaction (i.e. `ZNSRegistrar.registerRootDomain()` -> `ZNSDomainToken.register()`) - Burn the respective token every time a domain is revoked atomically within the revoke transaction (`ZNSRegistrar.revokeDomain()` -> `ZNSDomainToken.revoke()`) - Determine and check owner of any given domain token by the tokenId -- Transfer/sell domain token to change the owner of the domain +- Transfer domain token when the Registry owner and token owner are the same; transfers atomically update the Registry owner. When owners differ (a controlled domain), standard transfers are disallowed; reassignment is performed via `ZNSRootRegistrar.assignDomainToken()`. - Serve as a standard ERC-721 token with all the functionality provided so the token can be traded and managed by other applications. ## Resolvers, [ZNSStringResolver](./contracts/resolver/ZNSStringResolver.md) and [ZNSAddressResolver](./contracts/resolver/ZNSAddressResolver.md) @@ -61,7 +61,7 @@ The zNS system is expected to have multiple Resolver contracts, each being respo A resolver is structured to be a simple contract, having a mapping of a domain namehash to the specific source type (e.g. `bytes32 => address` OR `bytes32 => bytes`, etc.). Each Resolver can support one data type at a time or can be a combined one, supporting multiple. -The only resolver currently implemented is `ZNSAddressResolver`. It supports only address data type and has a simple mapping of `bytes32 domainHash => address contentAddress`. +Two resolvers are implemented today: `ZNSAddressResolver` (address) and `ZNSStringResolver` (string). The address resolver has a simple mapping of `bytes32 domainHash => address contentAddress`. ### Key responsibilities - Provide a straightforward binging of a domain namehash to specific domain source data (e.g. `hash("cooldomainname") => 0x1bc5d767ff…`) @@ -152,6 +152,7 @@ Many other contract functions have `onlyRegistrar()` modifiers which make sure t - Provide the main function for registering Root Domains, make sure that operations, especially ones using other contracts are performed properly and in proper sequence. Combine logic of other contracts in one atomic transaction. Check name existence, take the stake from the user, mint a domain token, set the data in `ZNSRegistry`. - Provide the main function for reclaiming full domain ownership for owners of the specific Domain Token. Ensure that only the owner of the actual ERC-721 token owner can do this, call `ZNSRegistry` to update the owner in records. - Provide the main function for revoking domains. Make sure that the only address allowed to revoke owns both the name, in the domain record held by the `ZNSRegistry` and the token, held by`ZNSDomainToken`. This will call `ZNSRegistry` to delete record, `ZNSDomainToken` to burn the token, and `ZNSTreasury` to unstake if needed. +- Use `rootPaymentType` to determine whether root domain registrations use `DIRECT` (no stake fee) or `STAKE` payment flows. ## [ZNSSubRegistrar](./contracts/registrar/ZNSSubRegistrar.md) Contract responsible for the registration of subdomains and distribution configs for domains of all levels that are used to set and determine diff --git a/docs/contracts/access/AAccessControlled.md b/docs/contracts/access/AAccessControlled.md index 9e0004c23..bebf68f05 100644 --- a/docs/contracts/access/AAccessControlled.md +++ b/docs/contracts/access/AAccessControlled.md @@ -88,9 +88,9 @@ function _setAccessController(address _accessController) internal Internal function to set the access controller address. -This function checks if the caller has the admin role in the current +This function checks if the caller has the GOVERNOR_ROLE in the current in-state contract and checks if the new access controller address passed is in fact a `ZNSAccessController` -contract that is already set up with the same caller as an admin. This prevents from setting the wrong address. +contract that is already set up with the same caller as GOVERNOR. This prevents from setting the wrong address. #### Parameters diff --git a/docs/contracts/price/ZNSCurvePricer.md b/docs/contracts/price/ZNSCurvePricer.md index ef5edadcf..6c2296b57 100644 --- a/docs/contracts/price/ZNSCurvePricer.md +++ b/docs/contracts/price/ZNSCurvePricer.md @@ -178,9 +178,6 @@ what we care about, then multiplied by the same precision multiplier to get the with truncated values past precision. So having a value of `15.235234324234512365 * 10^18` with precision `2` would give us `15.230000000000000000 * 10^18` -If the `rawPrice` calculated before truncation is less than the `precisionMultiplier` set, -we return the `precisionMultiplier` as the price to avoid returning 0. - #### Parameters | Name | Type | Description | diff --git a/docs/contracts/registrar/IZNSRootRegistrar.md b/docs/contracts/registrar/IZNSRootRegistrar.md index 9e21ec4f0..49e399bdb 100644 --- a/docs/contracts/registrar/IZNSRootRegistrar.md +++ b/docs/contracts/registrar/IZNSRootRegistrar.md @@ -66,6 +66,20 @@ Reverted when trying to assign a token to address that is already an owner | domainHash | bytes32 | The hash of the domain | | currentOwner | address | The address that is already an owner of the token | +### InvalidRootPaymentType + +```solidity +error InvalidRootPaymentType(enum IDistributionConfig.PaymentType paymentType) +``` + +Reverted when trying to set new `rootPaymentType` that is not supported. + +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| paymentType | enum IDistributionConfig.PaymentType | The payment type passed to the setter | + ### DomainRegistered ```solidity @@ -196,10 +210,24 @@ Emitted when the `subRegistrar` address is set in state. | ---- | ---- | ----------- | | subRegistrar | address | The new address of the SubRegistrar contract | +### RootPaymentTypeSet + +```solidity +event RootPaymentTypeSet(enum IDistributionConfig.PaymentType newRootPaymentType) +``` + +Emitted when the `rootPaymentType` is set in state. + +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| newRootPaymentType | enum IDistributionConfig.PaymentType | The new type of payment for root domains | + ### initialize ```solidity -function initialize(address accessController_, address registry_, address rootPricer_, bytes priceConfig_, address treasury_, address domainToken_) external +function initialize(address accessController_, address registry_, address rootPricer_, bytes priceConfig_, address treasury_, address domainToken_, enum IDistributionConfig.PaymentType rootPaymentType_) external ``` ### registerRootDomain @@ -250,6 +278,12 @@ function setRootPricerAndConfig(address rootPricer_, bytes priceConfig_) externa function setRootPriceConfig(bytes priceConfig_) external ``` +### setRootPaymentType + +```solidity +function setRootPaymentType(enum IDistributionConfig.PaymentType rootPaymentType_) external +``` + ### setTreasury ```solidity @@ -292,6 +326,12 @@ function rootPricer() external returns (contract IZNSPricer) function rootPriceConfig() external returns (bytes) ``` +### rootPaymentType + +```solidity +function rootPaymentType() external returns (enum IDistributionConfig.PaymentType) +``` + ### treasury ```solidity diff --git a/docs/contracts/registrar/ZNSRootRegistrar.md b/docs/contracts/registrar/ZNSRootRegistrar.md index 7be423d74..85b1534d7 100644 --- a/docs/contracts/registrar/ZNSRootRegistrar.md +++ b/docs/contracts/registrar/ZNSRootRegistrar.md @@ -15,23 +15,6 @@ they only check `REGISTRAR_ROLE` that can, in theory, be assigned to any other a This contract is also called at the last stage of registering subdomains, since it has the common logic required to be performed for any level domains. -### rootPricer - -```solidity -contract IZNSPricer rootPricer -``` - -Address of the `IZNSPricer` type contract that is used for root domains. - -### rootPriceConfig - -```solidity -bytes rootPriceConfig -``` - -The price config for the root domains, encoded as bytes. -This is used by the `IZNSPricer` to determine the price for root domains. - ### treasury ```solidity @@ -58,6 +41,31 @@ contract IZNSSubRegistrar subRegistrar The `ZNSSubRegistrar` contract that is used to handle subdomain registrations. This contract is used to set distribution configs and manage subdomain registrations. +### rootPricer + +```solidity +contract IZNSPricer rootPricer +``` + +Address of the `IZNSPricer` type contract that is used for root domains. + +### rootPriceConfig + +```solidity +bytes rootPriceConfig +``` + +The price config for the root domains, encoded as bytes. +This is used by the `IZNSPricer` to determine the price for root domains. + +### rootPaymentType + +```solidity +enum IDistributionConfig.PaymentType rootPaymentType +``` + +The `PaymentType` used for all root domains. + ### constructor ```solidity @@ -67,7 +75,7 @@ constructor() public ### initialize ```solidity -function initialize(address accessController_, address registry_, address rootPricer_, bytes priceConfig_, address treasury_, address domainToken_) external +function initialize(address accessController_, address registry_, address rootPricer_, bytes priceConfig_, address treasury_, address domainToken_, enum IDistributionConfig.PaymentType rootPaymentType_) external ``` Create an instance of the `ZNSRootRegistrar` @@ -86,6 +94,7 @@ to apply Access Control and ensure only the ADMIN can set the addresses. | priceConfig_ | bytes | IZNSPricer pricer config data encoded as bytes for root domains | | treasury_ | address | Address of the ZNSTreasury contract | | domainToken_ | address | Address of the ZNSDomainToken contract | +| rootPaymentType_ | enum IDistributionConfig.PaymentType | The payment type for root domains | ### registerRootDomain @@ -316,6 +325,21 @@ Setter for `ZNSSubRegistrar` contract in state. Only ADMIN can call this functio | ---- | ---- | ----------- | | subRegistrar_ | address | Address of the `ZNSSubRegistrar` contract | +### setRootPaymentType + +```solidity +function setRootPaymentType(enum IDistributionConfig.PaymentType rootPaymentType_) public +``` + +Setter for the root payment type in state. +Only ADMIN in `ZNSAccessController` can call this function. + +#### Parameters + +| Name | Type | Description | +| ---- | ---- | ----------- | +| rootPaymentType_ | enum IDistributionConfig.PaymentType | The new root payment type to set > Can be either `PaymentType.DIRECT` or `PaymentType.STAKE` | + ### pauseRegistration ```solidity diff --git a/docs/roles.md b/docs/roles.md index a5ed6d1be..35be6007d 100644 --- a/docs/roles.md +++ b/docs/roles.md @@ -16,22 +16,21 @@ contracts. - `ZNSAddressResolver` - `ZNSDomainToken` - `ZNSTreasury` -- The function `ZNSRootRegister.setRootPricer()` allows admins to update the pricer contract used to determine pricing for root -domains. -- The function `ZNSRootRegister.setTreasury()` allows admins to update the `ZNSTreasury` contract used to store protocol fees -and staked funds. -- The function `ZNSRootRegister.setDomainToken()` allows admins to update the domain token contract used to validate domain -ownership. -- The function `ZNSRootRegister.setSubRegistrar()` allows admins to update the subdomain registrar contract. -- The function `ZNSRootRegister.setAddressResolver()` allows admins to update the root domain resolver. +- The function `ZNSRootRegistrar.setRootPricerAndConfig()` allows admins to set the root pricer and validate/store the root price configuration for root domains. +- The function `ZNSRootRegistrar.setRootPriceConfig()` allows admins to update the price configuration for the currently set root pricer. +- The function `ZNSRootRegistrar.setTreasury()` allows admins to update the `ZNSTreasury` contract used to store protocol fees +and staked funds. +- The function `ZNSRootRegistrar.setDomainToken()` allows admins to update the domain token contract used to validate domain +ownership. +- The function `ZNSRootRegistrar.setSubRegistrar()` allows admins to update the subdomain registrar contract. +- The functions `ZNSRegistry.addResolverType()` and `ZNSRegistry.deleteResolverType()` allow admins to manage resolver implementations mapped by resolver type strings (e.g., "address"). Root resolvers are not set on `ZNSRootRegistrar`; resolver selection is performed via the `ZNSRegistry` resolver type mapping. +- The function `ZNSRootRegistrar.setRootPaymentType()` allows admins to set the root payment modality (`DIRECT` or `STAKE`) used by `registerRootDomain()`. - The admins can grant `REGISTRAR_ROLE` to addresses. ## `REGISTRAR_ROLE` privileges: -- The function `ZNSRootRegister.coreRegister()` allows registrars to register domains. +- The function `ZNSRootRegistrar.coreRegister()` allows registrars to register domains. - The function `ZNSRegistry.createDomainRecord()` allows registrars to register domain records which track ownership and address resolver. -- The function `ZNSRegistry.addResolverType` allows admins to add new types of resolvers -- The function `ZNSRegistry.deleteResolverType` allows admins to remove an existing type of resolver. - The function `ZNSDomainToken.register()` allows registrars to mint tokens which are used to validate domain ownership. - The function `ZNSDomainToken.revoke()` allows registrars to burn tokens to revoke domain ownership. - The function `ZNSTreasury.stakeForDomain()` allows registrars to process registration fee to beneficiaries and stake domain funds