This repository implements the ExtendedOptimismMintableToken.sol
. The Extended Optimism Mintable Token contract is an ERC-20 compatible token,
and is based on Optimism's OptimismMintableERC20
contract. It allows minting/burning of tokens by a specified bridge, pausing all activity, freezing of individual
addresses ("blacklisting"), and a way to upgrade the contract so that bugs can be fixed or features added. It also supports gas abstraction functionality by implementing EIP-3009 and using OpenZeppelin's upgradeable EIP-2612 implementation. We describe this functionality further under Functionality. Finally, it uses OpenZeppelin's AccessControl pattern to use role-based access control for the pausing and blacklisting capabilities, designating a role to manage each, along with a DEFAULT_ROLE_ADMIN
role to manage those roles (detailed further below).
The ExtendedOptimismMintableToken
inherits from the UpgradeableOptimismMintableERC20
contract, which itself is based off of Optimism's OptimismMintableERC20 contract. The UpgradeableOptimismMintableERC20
contains the following changes from Optimism's OptimismMintableERC20
:
- OpenZeppelin's
ERC20Upgradeable
contract is used in place of theirERC20
contract to support upgradeability. - OpenZeppelin's
IERC165Upgradeable
contract is used in place of theirIERC165
contract to support upgradeability. supportsInterface
is marked aspublic virtual
to allow inheriting contracts to both override and call it.- Marks
mint
andburn
aspublic
instead ofexternal
to allow inheriting contracts to call them. - An
initialize
initializer function was added to support the initialization ofERC20Upgradeable
configuration. - A
decimals
variable was added to the constructor. - A storage gap was added to simplify state management in the event that state variables are added to
UpgradeableOptimismMintableERC20
in the future.
Requirements:
- Node >= v12
- Yarn
- The required versions of the Optimism repo and Foundry are specified in the .env file
- Run
make install-foundry
to installFoundry
at this linked commit. - Run
make build
to install dependencies. - Run
make tests
to run tests. - Run
make coverage
to get code coverage. - Set the required .env variables and run
make deploy
to simulate Base Mainnet token deployment locally.
- Note: To initialize the
ExtendedOptimismMintableToken
contract, you need to call theinitialize
method inherited fromUpgradeableOptimismMintableERC20
, and thenExtendedOptimismMintableToken
'sinitializeV2
method. - Configure the following variables in
.env
:DEPLOYER
- the address deploying the token implementation and proxy contract.ADMIN
- the address to be theadmin
of the token's proxy contract. Not to be confused with theDEFAULT_ROLE_ADMIN
env variable and role specified below, which administrates theblacklister
andpauser
roles along with itself.L2_BRIDGE
- the address of theL2StandardBridge
contract which is able to mint and burn the token being deployed.REMOTE_TOKEN
- the L1 address of the L2 bridged token being deployed.NAME
- theERC20
name
of the bridged token. This is also used for theEIP-712
domain separatorname
.SYMBOL
- theERC20
symbol
of the bridged token.DECIMALS
- theERC20
decimals
of the bridged token.PAUSER
- the only address for the role that can pause the contract, which prevents all transfers, minting, and burningBLACKLISTER
- the only address for the role that can callblacklist(address)
, which prevents all transfers to or from that address, andunBlacklist(address)
DEFAULT_ROLE_ADMIN
- the address for the role which can re-assign itself and thePAUSER
andBLACKLISTER
roles. This role can NOT change theADMIN
address, which administrates the proxy contract.
- Run
make deploy
to simulate Base Mainnet token deployment locally.
These scripts can be found in the script/
directory:
DeployExtendedOptimismMintableToken.s.sol
to deploy and configure a totally newExtendedOptimismMintableToken
implementation and corresponding proxy contractsUpgradeToExtendedOptimismMintableToken.s.sol.s.sol
to upgrade an already deployedUpgradeableOptimismMintableERC20
to anExtendedOptimismMintableToken
DeployExtendedOptimismMintableTokenImpl.s.sol
to deploy and configure anExtendedOptimismMintableToken
implementation contract
These scripts are tested in test/script
directory.
The ExtendedOptimismMintableToken
allows the BRIDGE
address to create (mint
) and destroy (`burn``) tokens.
As on Optimism's OptimismMintableERC20
contract, the BRIDGE
mints tokens via the mint
method. It specifies the
amount
of tokens to create, and a _to
address which will own the newly
created tokens. The balance of the _to
address and totalSupply
will each
increase by amount
.
- Only the
BRIDGE
may callmint
. - Minting fails when the contract is
paused
. - Minting fails when the
BRIDGE
or_to
address is blacklisted. - Minting emits a
Mint(_to, amount)
event and aTransfer(0x00, _to, amount)
event.
As on Optimism's OptimismMintableERC20
contract, the BRIDGE
burns tokens via the burn
method. It specifies the
The BRIDGE
specifies the address _from
whose tokens are burned (i.e. whose balance of the token, along with the totalSupply
of the token, are reduced by amount
) and the
amount
of tokens to burn. The _from
address must have a balance
greater than
or equal to the amount
. The abillity to burn tokens is restricted to the BRIDGE
address.
-
Only the
BRIDGE
address may call burn. -
Burning fails when the contract is paused.
-
Burning fails when the calling address is blacklisted.
-
Burning fails when the
_from
address is blacklisted. -
Burning emits a
Burn(_from_, amount)
event, and aTransfer(_from_, 0x00, amount)
event.
Addresses can be blacklisted. A blacklisted address will be unable to participate in the approval, increase or decrease of allowances and will be unable to transfer, mint, or burn tokens.
Coinbase blacklists an address via the blacklist
method. The specified account
will be added to the blacklist.
- Only the
blacklister
role may callblacklist
. - Blacklisting emits a
Blacklist(account)
event
Coinbase removes an address from the blacklist via the unblacklist
method. The
specified account
will be removed from the blacklist.
- Only the
blacklister
role may callunblacklist
. - Unblacklisting emits an
UnBlacklist(account)
event.
The entire contract can be paused in case a serious bug is found or there is a serious key compromise. All transfers, minting, and burning will be prevented while the contract is paused. Other functionality, such as modifying the blacklist, changing roles, and upgrading will remain operational as those methods may be required to fix or mitigate the issue that caused Coinbase to pause the contract.
Coinbase will pause the contract via the pause
method. This method will set the
paused flag to true.
-
Only the
pauser
role may call pause. -
Pausing emits a
Pause()
event
Coinbase will unpause the contract via the unpause
method. This method will set
the paused
flag to false. All functionality will be restored when the contract
is unpaused.
-
Only the
pauser
role may call unpause. -
Unpausing emits an
Unpause()
event
The ExtendedOptimismMintableToken
implements EIP-3009, with the additional requirement that transfers via this functionality not be called with blacklisted from
or to
addresses, nor while the contract is paused.
The ExtendedOptimismMintableToken
uses OpenZeppelin's EIP-2612 upgradeable implementation, and adds the requirement that permit
not be called with blacklisted owner
or spender
addresses, nor while the contract is paused.
The Extended OptimismMintable Token uses the Unstructured-Storage Proxy pattern
[https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies]. The contracts use storage gaps to simplify state management in the event that state variables are added to in future upgrades. ExtendedOptimismMintableToken.sol
is the implementation, the
actual token address will be a Proxy contract
(using the code from Optimism's Proxy.sol) which will forward all
calls to ExtendedOptimismMintableToken
via delegatecall. This pattern allows Coinbase to upgrade the
logic of any deployed tokens seamlessly.
- Coinbase will upgrade the token via a call to
upgradeTo
orupgradeToAndCall
if initialization is required for the new version. - Only the Proxy contract's
admin
role may callupgradeTo
orupgradeToAndCall
. - For upgrades, if an initializer method is used, set a constant version in the
reinitializer
modifier that is incremented from the previous upgrade's version. This prevents the initializer method from being called multiple times. Failing to follow this guidance could introduce vulnerabilities. Additionally, note subsequently introducedreinitializer
methods are not meant to re-execute the same initialization code used in previous versions.
The roles (blacklister
, pauser
) described above may be reassigned. The DEFAULT_ROLE_ADMIN
role has the ability to
reassign itself and the blacklister
and pauser
roles. It cannot re-assign the Proxy contract's admin
role. The BRIDGE
address is immutable, in keeping with the OptimismMintableERC20
contract.
changeRolesAdmin
updates theDEFAULT_ROLE_ADMIN
role to a new address.changeRolesAdmin
may only be called by theDEFAULT_ROLE_ADMIN
role.
In general, function parameters should be named, are not prefixed with underscores and are written in camelCase.
We have deviated from this guideline in the following cases. Where referencing code from other codebases, we have followed their parameter styling convention (ex. prefixing parameters with an underscore in the mint
and burn
methods as the Optimism repo does for their OptimismMintableERC20 contract, OpenZeppelin ERC20 methods, etc). For consistency, in methods like initializeV2
where one parameter (_name
) is prefixed with an underscore (in this case to differentiate it from the storage variable it's meant to fill), we prefix the other parameters for the same function with an underscore. Parameter names in renounceRole
on ExtendedOptimismMintableToken
are not named as they would be unused - in this case, the parameters are included to override the same-named method from the AccessControlUpgradable
contract.
This work uses software from The Optimism Monorepo:
title: The Optimism Monorepo
authors:
- name: The Optimism Collective
version: 1.0.0
year: 2020
url: https://github.com/ethereum-optimism/optimism
repository: https://github.com/ethereum-optimism/optimism
license: MIT
Where this code indicates it uses code from the CENTRE codebase, it references this commit https://github.com/centrehq/centre-tokens/commit/0d3cab14ebd133a83fc834dbd48d0468bdf0b391
I.e. from the CENTRE Fiat Token codebase, we specifically reference: