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. TheminterManagercontract 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 theMasterMintercontract, andMasterMinterwill call the appropriate functions on theminterManager.minter- eachminteris managed by one or morecontroller. Themintercannot 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 theminterand sets its minting allowance.removeMinter(minter)- Disables theminterand sets its minting allowance to 0.isMinter(minter)- Returnstrueif theminteris enabled, andfalseotherwise.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 thecontrollerto callconfigureMinter,incrementMinterAllowanceandremoveMinter. Note:configureController(controller, 0x00)is forbidden because it has the effect of removing the controller.removeController(controller)- The owner disables the controller by setting itsminterto0x00.setMinterManager(minterManager)- The owner sets a new contract to theminterManageraddress. This has no effect on the oldminterManagercontract. If the newminterManagerdoes not implement theMinterManagementInterfaceor does not give this instance of theMasterMintercontract permission to call minter management functions then thecontrollercalls toconfigureMinter,incrementMinterAllowance, andremoveMinterwill throw.configureMinter(allowance)- A controller enables its minter and sets its allowance. TheMasterMintercontract will call theminterManagercontract on thecontroller's behalf.incrementMinterAllowance- A controller increments the allowance of an enabled minter (incrementMinterAllowancewill throw if theminteris disabled). TheMasterMintercontract will call theminterManagercontract on thecontroller's behalf.removeMinter- A controller disables aminter. TheMasterMintercontract will call theminterManagercontract on thecontroller's behalf.
The MasterMinter may be deployed independently of the FiatToken contract
(e.g. USDC).
- FiatToken then MasterMinter. Deploy
MasterMinterand set theminterManagerto point to theFiatTokenin the constructor. Then use theMasterMinterownerrole to configure at least onecontrollerfor each existingminterin theFiatToken. Once theMasterMinteris fully configured, use theFiatTokenownerrole to broadcast anupdateMasterMintertransaction settingmasterMinterrole to theMasterMintercontract address. - MasterMinter then FiatToken. Deploy
MasterMinterand set theminterManagerto point to address0x00in the constructor. Then deploy theFiatTokenand set themasterMinterto be the address of theMasterMintercontract in the constructor. Next, use theMasterMinterownerto set theminterManagerand configurecontrollers.
We recommend assigning at least two controllers to each minter.
- AllowanceController. Use this
controllerto enable theminterwith a singleconfigureMintertransaction, and then use it exclusively to signincrementMinterAllowancetransactions. There may be multipleAllowanceControllersthat sign different size allowance increment transactions. - SecurityController. Use this
controllerto sign a singleremoveMintertransaction 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.