The MasterMinter is a governance contract. It delegates the functionality of the
masterMinter
role in the Circle FiatToken contract to multiple addresses. (The
masterMinter
role can add and remove minters from a FiatToken and set their
allowances.) The MasterMinter contract delegates the minter management
capability to controllers
. Each controller
manages exactly one minter
, and
a single minter
may be managed by multiple controllers
. This allows
separation of duties (offline key management) and simplifies nonce management
for warm transactions.
Minters and FiatToken holders are not affected by replacing a masterMinter
user address with a MasterMinter
contract.
The MasterMinter
contract has the following roles:
owner
- adds and removes controllers, sets the address of theminterManager
, and sets the owner.minterManager
- address of a contract (e.g. USDC) with aMinterManagementInterface
. TheminterManager
contract stores information about minter allowances and which minters are enabled/disabled.controller
- each controller manages exactly one minter. A controller can enable/disable its minter, and modify the minting allowance by calling functions on theMasterMinter
contract, andMasterMinter
will call the appropriate functions on theminterManager
.minter
- eachminter
is managed by one or morecontroller
. Theminter
cannot perform any actions on the MasterMinter contract. It interacts only with the FiatToken contract.
The owner
of the FiatToken contract can set the masterMinter
role to point
to the address of the MasterMinter
contract. This enables the MasterMinter
contract to call minter management functions on the FiatToken contract:
configureMinter(minter, allowance)
- Enables theminter
and sets its minting allowance.removeMinter(minter)
- Disables theminter
and sets its minting allowance to 0.isMinter(minter)
- Returnstrue
if theminter
is enabled, andfalse
otherwise.minterAllowance(minter)
- Returns the minting allowance of theminter
.
Together, these four functions are defined as the MinterManagementInterface
.
The MasterMinter
contains the address of a minterManager
that implements the
MinterManagementInterface
. The MasterMinter
interacts with the FiatToken
contract via the minterManager
.
When a controller
calls a function on MasterMinter
, the MasterMinter
will
call the appropriate function on the FiatToken
contract on its behalf. Both
the MasterMinter
and the FiatToken
do their own access control.
configureController(controller, minter)
- The owner assigns the controller to manage the minter. This allows thecontroller
to callconfigureMinter
,incrementMinterAllowance
andremoveMinter
. Note:configureController(controller, 0x00)
is forbidden because it has the effect of removing the controller.removeController(controller)
- The owner disables the controller by setting itsminter
to0x00
.setMinterManager(minterManager)
- The owner sets a new contract to theminterManager
address. This has no effect on the oldminterManager
contract. If the newminterManager
does not implement theMinterManagementInterface
or does not give this instance of theMasterMinter
contract permission to call minter management functions then thecontroller
calls toconfigureMinter
,incrementMinterAllowance
, andremoveMinter
will throw.configureMinter(allowance)
- A controller enables its minter and sets its allowance. TheMasterMinter
contract will call theminterManager
contract on thecontroller
's behalf.incrementMinterAllowance
- A controller increments the allowance of an enabled minter (incrementMinterAllowance
will throw if theminter
is disabled). TheMasterMinter
contract will call theminterManager
contract on thecontroller
's behalf.removeMinter
- A controller disables aminter
. TheMasterMinter
contract will call theminterManager
contract on thecontroller
's behalf.
The MasterMinter
may be deployed independently of the FiatToken
contract
(e.g. USDC).
- FiatToken then MasterMinter. Deploy
MasterMinter
and set theminterManager
to point to theFiatToken
in the constructor. Then use theMasterMinter
owner
role to configure at least onecontroller
for each existingminter
in theFiatToken
. Once theMasterMinter
is fully configured, use theFiatToken
owner
role to broadcast anupdateMasterMinter
transaction settingmasterMinter
role to theMasterMinter
contract address. - MasterMinter then FiatToken. Deploy
MasterMinter
and set theminterManager
to point to address0x00
in the constructor. Then deploy theFiatToken
and set themasterMinter
to be the address of theMasterMinter
contract in the constructor. Next, use theMasterMinter
owner
to set theminterManager
and configurecontrollers
.
We recommend assigning at least two controllers
to each minter
.
- AllowanceController. Use this
controller
to enable theminter
with a singleconfigureMinter
transaction, and then use it exclusively to signincrementMinterAllowance
transactions. There may be multipleAllowanceControllers
that sign different size allowance increment transactions. - SecurityController. Use this
controller
to sign a singleremoveMinter
transaction and store it for emergencies.
This configuration allows the removeMinter
transaction to be presigned as
nonces for the SecurityController
are deterministic, which reduces the time to
respond when there's an issue. Broadcasting the removeMinter
transaction will
cause all future interactions from the AllowanceController
to throw
.
Creating a MasterMinter
contract that inherits from a MintController
contract with no changes may seem like a curious design choice. This leaves open
the possibility of creating other contracts that inherit from MintController
without creating naming confusion due to their different functionality.