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 the
minterManager, and sets the owner.minterManager - address of a contract (e.g. USDC) with a
MinterManagementInterface. The minterManager 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 the MasterMinter contract, and MasterMinter will call the
appropriate functions on the minterManager.minter - each minter is managed by one or more controller. The minter
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 the minter and sets its
minting allowance.removeMinter(minter) - Disables the minter and sets its minting allowance
to 0.isMinter(minter) - Returns true if the minter is enabled, and false
otherwise.minterAllowance(minter) - Returns the minting allowance of the minter.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 the controller to call configureMinter,
incrementMinterAllowance and removeMinter. Note:
configureController(controller, 0x00) is forbidden because it has the effect
of removing the controller.removeController(controller) - The owner disables the controller by setting
its minter to 0x00.setMinterManager(minterManager) - The owner sets a new contract to the
minterManager address. This has no effect on the old minterManager
contract. If the new minterManager does not implement the
MinterManagementInterface or does not give this instance of the
MasterMinter contract permission to call minter management functions then
the controller calls to configureMinter, incrementMinterAllowance, and
removeMinter will throw.configureMinter(allowance) - A controller enables its minter and sets its
allowance. The MasterMinter contract will call the minterManager contract
on the controller’s behalf.incrementMinterAllowance - A controller increments the allowance of an
enabled minter (incrementMinterAllowance will throw if the minter
is disabled). The MasterMinter contract will call the minterManager
contract on the controller’s behalf.removeMinter - A controller disables a minter. The MasterMinter contract
will call the minterManager contract on the controller’s behalf.The MasterMinter may be deployed independently of the FiatToken contract
(e.g. USDC).
MasterMinter and set the
minterManager to point to the FiatToken in the constructor. Then use the
MasterMinter owner role to configure at least one controller for each
existing minter in the FiatToken. Once the MasterMinter is fully
configured, use the FiatToken owner role to broadcast an
updateMasterMinter transaction setting masterMinter role to the
MasterMinter contract address.MasterMinter and set the
minterManager to point to address 0x00 in the constructor. Then deploy the
FiatToken and set the masterMinter to be the address of the MasterMinter
contract in the constructor. Next, use the MasterMinter owner to set the
minterManager and configure controllers.We recommend assigning at least two controllers to each minter.
controller to enable the minter with
a single configureMinter transaction, and then use it exclusively to sign
incrementMinterAllowance transactions. There may be multiple
AllowanceControllers that sign different size allowance increment
transactions.controller to sign a single
removeMinter 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.