feat: implement `CommunityTokenDeployer` contract (#2)
This commit introduces the `CommunityTokenDeployer` contract discussed
in https://github.com/status-im/status-desktop/issues/11954.
The idea is that, instead of having accounts deploy `OwnerToken` and
`MasterToken` directly, they'd use a deployer contract instead, which
maintains a registry of known `OwnerToken` addresses, mapped to Status
community addresses.
The following changes have been made:
It was, and still is, a requirement that both, `OwnerToken` and
`MasterToken` are deployed within a single transaction, so that when
something goes wrong, we don't end up in an inconsistent state.
That's why `OwnerToken` used to instantiated `MasterToken` and required
all of its constructor arguments as well.
Unfortunately, this resulted in compilation issues in the context of the
newly introduce deployer contract, where there are too many function
arguments.
Because we now delegate deployment to a dedicated contract, we can
instantiate both `OwnerToken` and `MasterToken` in a single transaction,
without having `OwnerToken` being responsible to instantiate
`MasterToken`.
This fixes the compilation issues and simplifies the constructor of
`OwnerToken`.
The new `CommunityTokenDeployer` contract is now responsble for
deploying the aforementioned tokens and ensures that they are deployed
within a single transaction.
To deploy an `OwnerToken` and `MasterToken` accounts can now call
`CommunityDeloyerToken.deploy(TokenConfig, TokenConfig,
DeploymentSignature)`.
The `DeploymentSignature` uses `EIP712` structured type hash data to let
the contract verify that the deployer is allowed to deploy the contracts
on behalf of a community account.
2023-09-19 09:39:55 +00:00
|
|
|
// SPDX-License-Identifier: UNLICENSED
|
|
|
|
pragma solidity ^0.8.17;
|
|
|
|
|
|
|
|
import { ITokenFactory } from "../interfaces/ITokenFactory.sol";
|
2023-09-22 10:23:00 +00:00
|
|
|
import { Ownable2Step } from "@openzeppelin/contracts/access/Ownable2Step.sol";
|
feat: implement `CommunityTokenDeployer` contract (#2)
This commit introduces the `CommunityTokenDeployer` contract discussed
in https://github.com/status-im/status-desktop/issues/11954.
The idea is that, instead of having accounts deploy `OwnerToken` and
`MasterToken` directly, they'd use a deployer contract instead, which
maintains a registry of known `OwnerToken` addresses, mapped to Status
community addresses.
The following changes have been made:
It was, and still is, a requirement that both, `OwnerToken` and
`MasterToken` are deployed within a single transaction, so that when
something goes wrong, we don't end up in an inconsistent state.
That's why `OwnerToken` used to instantiated `MasterToken` and required
all of its constructor arguments as well.
Unfortunately, this resulted in compilation issues in the context of the
newly introduce deployer contract, where there are too many function
arguments.
Because we now delegate deployment to a dedicated contract, we can
instantiate both `OwnerToken` and `MasterToken` in a single transaction,
without having `OwnerToken` being responsible to instantiate
`MasterToken`.
This fixes the compilation issues and simplifies the constructor of
`OwnerToken`.
The new `CommunityTokenDeployer` contract is now responsble for
deploying the aforementioned tokens and ensures that they are deployed
within a single transaction.
To deploy an `OwnerToken` and `MasterToken` accounts can now call
`CommunityDeloyerToken.deploy(TokenConfig, TokenConfig,
DeploymentSignature)`.
The `DeploymentSignature` uses `EIP712` structured type hash data to let
the contract verify that the deployer is allowed to deploy the contracts
on behalf of a community account.
2023-09-19 09:39:55 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @title BaseTokenFactory contract
|
|
|
|
* @author 0x-r4bbit
|
|
|
|
*
|
|
|
|
* This contract provides shared functionality across token factory contracts
|
|
|
|
* that are used to create instances of `OwnerToken` and `MasterToken`.
|
|
|
|
* This includes a custom modifiers as well as a function to set the token deployer
|
|
|
|
* address that is needed for it.
|
|
|
|
*
|
|
|
|
* @dev Other factory contract inherit from this contract.
|
|
|
|
*/
|
2023-09-22 10:23:00 +00:00
|
|
|
abstract contract BaseTokenFactory is ITokenFactory, Ownable2Step {
|
feat: implement `CommunityTokenDeployer` contract (#2)
This commit introduces the `CommunityTokenDeployer` contract discussed
in https://github.com/status-im/status-desktop/issues/11954.
The idea is that, instead of having accounts deploy `OwnerToken` and
`MasterToken` directly, they'd use a deployer contract instead, which
maintains a registry of known `OwnerToken` addresses, mapped to Status
community addresses.
The following changes have been made:
It was, and still is, a requirement that both, `OwnerToken` and
`MasterToken` are deployed within a single transaction, so that when
something goes wrong, we don't end up in an inconsistent state.
That's why `OwnerToken` used to instantiated `MasterToken` and required
all of its constructor arguments as well.
Unfortunately, this resulted in compilation issues in the context of the
newly introduce deployer contract, where there are too many function
arguments.
Because we now delegate deployment to a dedicated contract, we can
instantiate both `OwnerToken` and `MasterToken` in a single transaction,
without having `OwnerToken` being responsible to instantiate
`MasterToken`.
This fixes the compilation issues and simplifies the constructor of
`OwnerToken`.
The new `CommunityTokenDeployer` contract is now responsble for
deploying the aforementioned tokens and ensures that they are deployed
within a single transaction.
To deploy an `OwnerToken` and `MasterToken` accounts can now call
`CommunityDeloyerToken.deploy(TokenConfig, TokenConfig,
DeploymentSignature)`.
The `DeploymentSignature` uses `EIP712` structured type hash data to let
the contract verify that the deployer is allowed to deploy the contracts
on behalf of a community account.
2023-09-19 09:39:55 +00:00
|
|
|
error BaseTokenFactory_InvalidTokenDeployerAddress();
|
|
|
|
error BaseTokenFactory_NotAuthorized();
|
|
|
|
error BaseTokenFactory_InvalidTokenMetadata();
|
|
|
|
|
|
|
|
event TokenDeployerAddressChange(address indexed);
|
|
|
|
|
|
|
|
/// @dev The address of the token deployer contract.
|
|
|
|
address public tokenDeployer;
|
|
|
|
|
|
|
|
modifier onlyTokenDeployer() {
|
|
|
|
if (msg.sender != tokenDeployer) {
|
|
|
|
revert BaseTokenFactory_NotAuthorized();
|
|
|
|
}
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
modifier onlyValidTokenMetadata(string calldata name, string calldata symbol, string calldata baseURI) {
|
|
|
|
if (bytes(name).length == 0 || bytes(symbol).length == 0 || bytes(baseURI).length == 0) {
|
|
|
|
revert BaseTokenFactory_InvalidTokenMetadata();
|
|
|
|
}
|
|
|
|
_;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @notice Sets the token deployer address.
|
|
|
|
* @dev Only the owner can call this function.
|
|
|
|
* @dev Reverts if provided address is a zero address.
|
|
|
|
* @dev Emits a {TokenDeployerAddressChange} event.
|
|
|
|
* @param _tokenDeployer The address of the token deployer contract.
|
|
|
|
*/
|
|
|
|
function setTokenDeployerAddress(address _tokenDeployer) external onlyOwner {
|
|
|
|
if (_tokenDeployer == address(0)) {
|
|
|
|
revert BaseTokenFactory_InvalidTokenDeployerAddress();
|
|
|
|
}
|
|
|
|
tokenDeployer = _tokenDeployer;
|
|
|
|
emit TokenDeployerAddressChange(tokenDeployer);
|
|
|
|
}
|
|
|
|
}
|