@offchainlabs/stablecoin-evm
Version:
Circle's Stablecoin Smart Contracts on EVM-compatible blockchains
227 lines (165 loc) • 6.57 kB
Markdown
<!-- prettier-ignore-start -->
<!-- omit in toc -->
# Circle's Stablecoin Smart Contracts on EVM-compatible blockchains
<!-- prettier-ignore-end -->
This repository contains the smart contracts used by
[Circle's](https://www.circle.com/) stablecoins on EVM-compatible blockchains.
All contracts are written in [Solidity](https://soliditylang.org/) and managed
by the [Hardhat](https://hardhat.org/) framework.
<!-- prettier-ignore-start -->
<!-- omit in toc -->
## Table of contents
<!-- prettier-ignore-end -->
- [Setup](#setup)
- [Development Environment](#development-environment)
- [IDE](#ide)
- [Development](#development)
- [TypeScript type definition files for the contracts](#typescript-type-definition-files-for-the-contracts)
- [Linting and Formatting](#linting-and-formatting)
- [Testing](#testing)
- [Deployment](#deployment)
- [Contracts](#contracts)
- [FiatToken features](#fiattoken-features)
- [ERC20 compatible](#erc20-compatible)
- [Pausable](#pausable)
- [Upgradable](#upgradable)
- [Blacklist](#blacklist)
- [Minting/Burning](#mintingburning)
- [Ownable](#ownable)
- [Additional Documentations](#additional-documentations)
## Setup
### Development Environment
Requirements:
- Node 16.14.0
- Yarn 1.22.19
- [Foundry@f625d0f](https://github.com/foundry-rs/foundry/releases/tag/nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9)
```sh
$ 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 npm packages and other dependencies listed in setup.sh
```
### IDE
We recommend using VSCode for the project here with these
[extensions](./.vscode/extensions.json) installed.
## Development
### TypeScript type definition files for the contracts
Types are automatically generated as a part of contract compilation:
```sh
$ yarn compile
```
To generate typing without re-compiling, run
```sh
$ yarn hardhat typechain
```
### Linting and Formatting
To check code for problems:
```sh
$ yarn static-check # Runs a static check on the repo.
```
or run the checks individually:
```sh
$ 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
```
To auto-format code:
```sh
$ yarn fmt
```
### Testing
Run all tests:
```sh
$ yarn test
```
To run tests in a specific file, run:
```sh
$ yarn test [path/to/file]
```
To run tests and generate test coverage, run:
```sh
$ yarn coverage
```
To check the size of contracts in the repo, run the following command.
```sh
$ yarn contract-size # Ignores tests
```
## Deployment
1. Create a copy of the file `.env.example`, and name it `.env`. Fill in
appropriate values in the `.env` file. This file must not be checked into the
repository.
```sh
cp .env.example .env
```
2. Create a `blacklist.remote.json` file and populate it with a list of
addresses to be blacklisted. This file must not be checked into the
repository.
```sh
echo "[]" > blacklist.remote.json
```
3. Simulate a deployment by running the following command
```sh
yarn forge:simulate scripts/deploy/deploy-fiat-token.s.sol --rpc-url <testnet OR mainnet>
```
4. Validate that all transactions to be broadcasted are filled in with the
correct values
5. Deploy the contracts by running the following command
```sh
yarn forge:broadcast scripts/deploy/deploy-fiat-token.s.sol --rpc-url <testnet OR mainnet>
```
6. Verify the contracts on an Etherscan flavored block explorer by running the
following command. Ensure that `ETHERSCAN_KEY` is set in the `.env` file.
```sh
yarn forge:verify scripts/deploy/deploy-fiat-token.s.sol --rpc-url <testnet OR mainnet>
```
## Contracts
The FiatToken contracts adheres to OpenZeppelin's
[Proxy Upgrade Pattern](https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies)
([permalink](https://github.com/OpenZeppelin/openzeppelin-upgrades/blob/65cf285bd36af24570186ca6409341540c67238a/docs/modules/ROOT/pages/proxies.adoc#L1)).
There are 2 main contracts - an implementation contract
([`FiatTokenV2_2.sol`](./contracts/v2/FiatTokenV2_2.sol)) that contains the main
logic for FiatToken's functionalities, and a proxy contract
([`FiatTokenProxy.sol`](./contracts/v1/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.
## FiatToken features
The FiatToken offers a number of capabilities, which briefly are described
below. There are more [detailed design docs](./doc/tokendesign.md) in the `doc`
directory.
### ERC20 compatible
The FiatToken implements the ERC20 interface.
### Pausable
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.
### Upgradable
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.
### Blacklist
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.
### Minting/Burning
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`.
### Ownable
The contract has an Owner, who can change the `owner`, `pauser`, `blacklister`,
or `masterMinter` addresses. The `owner` can not change the `proxyOwner`
address.
## Additional Documentations
- [FiatToken design](./doc/tokendesign.md)
- [MasterMinter design](./doc/masterminter.md)
- [Bridged USDC Standard](./doc/bridged_USDC_standard.md)
- [Deployment process](./doc/deployment.md)
- [Preparing an upgrade](./doc/upgrade.md)
- [Upgrading from v2.1 to v2.2](./doc/v2.2_upgrade.md)
- [Celo FiatToken extension](./doc/celo.md)