This repository contains the smart contracts used by Circle's stablecoins on EVM-compatible blockchains. All contracts are written in Solidity and managed by the Truffle framework.
Requirements:
- Node 16.14.0
- Yarn 1.22.19
$ git clone git@github.com:circlefin/stablecoin-evm.git
$ cd stablecoin-evm
$ nvm use
$ npm i -g yarn@1.22.19 # Install yarn if you don't already have it
$ yarn install # Install dependencies
We recommend using VSCode for the project here with these extensions installed.
To generate type definitions:
$ yarn typechain
To check code for problems:
$ yarn static-check # Runs a static check on the repo.
or run the checks individually:
$ yarn typecheck # Type-check TypeScript code
$ yarn lint # Check JavaScript and TypeScript code
$ yarn lint --fix # Fix problems where possible
$ yarn solhint # Check Solidity code
$ yarn slither # Run Slither
To auto-format code:
$ yarn fmt
First, make sure Ganache is running.
$ yarn ganache
Run all tests:
$ yarn test
To run tests in a specific file, run:
$ yarn test [path/to/file]
To run tests and generate test coverage, run:
$ yarn coverage
To check the size of contracts in the repo, run the following command.
$ yarn contract-size # Ignores tests
$ yarn contract-size:all # Includes all contracts
Create a copy of the file config.js.example
, and name it config.js
. Enter
the BIP39 mnemonic phrase, the INFURA API key to use for deployment, and the
addresses of proxy admin, owner, master minter, blacklister, and pauser in
config.js
. This file must not be checked into the repository. To prevent
accidental check-ins, config.js
is in .gitignore
.
Create a copy of the file blacklist.test.json
, and name it
blacklist.remote.json
. Fill in blacklist.remote.json
with the list addresses
to blacklist. This file must not be checked into the repository. To prevent
accidental check-ins, blacklist.remote.json
is in .gitignore
.
Run yarn migrate --network NETWORK
, where NETWORK is either mainnet
or
ropsten
.
The FiatToken contracts adheres to OpenZeppelin's
Proxy Upgrade Pattern
(permalink).
There are 2 main contracts - an implementation contract
(FiatTokenV2_2.sol
) that contains the main
logic for FiatToken's functionalities, and a proxy contract
(FiatTokenProxy.sol
) that redirects
function calls to the implementation contract. This allows upgrading FiatToken's
functionalities, as a new implementation contact can be deployed and the Proxy
can be updated to point to it.
The FiatToken offers a number of capabilities, which briefly are described
below. There are more detailed design docs in the doc
directory.
The FiatToken implements the ERC20 interface.
The entire contract can be frozen, in case a serious bug is found or there is a
serious key compromise. No transfers can take place while the contract is
paused. Access to the pause functionality is controlled by the pauser
address.
A new implementation contract can be deployed, and the proxy contract will
forward calls to the new contract. Access to the upgrade functionality is
guarded by a proxyOwner
address. Only the proxyOwner
address can change the
proxyOwner
address.
The contract can blacklist certain addresses which will prevent those addresses
from transferring or receiving tokens. Access to the blacklist functionality is
controlled by the blacklister
address.
Tokens can be minted or burned on demand. The contract supports having multiple
minters simultaneously. There is a masterMinter
address which controls the
list of minters and how much each is allowed to mint. The mint allowance is
similar to the ERC20 allowance - as each minter mints new tokens their allowance
decreases. When it gets too low they will need the allowance increased again by
the masterMinter
.
The contract has an Owner, who can change the owner
, pauser
, blacklister
,
or masterMinter
addresses. The owner
can not change the proxyOwner
address.