These are the contracts that support the Circle Gateway product. See the contract docs or Circle's website for more information about the product and how to use it.
- Run
git submodule update --init --recursive
to update/download all libraries. - Ensure Yarn is installed and then run
yarn install
to install additional JS dependencies.
- Run
curl -L https://foundry.paradigm.xyz | bash
- Follow the instructions of that command to source env file
- run
foundryup --install v1.0.0
The deployment steps are:
- Deploy the
UpgradablePlaceholder
implementation - Deploy the actual implementation (e.g.
GatewayMinter
) - Deploy the ERC1967Proxy and setup the proxy:
- Deploy the ERC1967 Proxy, set the implementation to
UpgradablePlaceholder
and initialize the owner to Create2Factory address. - In the same transcation, upgrade the implementation to actual implementation and initialize the implementation properly.
- Deploy the ERC1967 Proxy, set the implementation to
The reason of setting owner of UpgradablePlaceholder
to Create2Factory address is that since the owner is part of the address computation, we want to use Create2Factory to avoid managing an extra EOA key.
Since the owner of UpgradablePlaceholder
is Create2Factory and only the owner can perform upgradeToAndCall
, we decided to use Create2Factory.deployAndMultiCall
to upgrade to actual implementation in the proxy deployment call.
Before deploying the contracts, ensure you have:
-
Create a
.env
file from.env.example
and set up environment variables in.env
file. -
Verified you have sufficient funds in the deployer account for the target network
Only needed for local deployment
Start a local RPC node at http://127.0.0.1:8485 by running anvil
.
Only needed for local and SMOKEBOX deployment
Run the following command to deploy a test instance of the Create2Factory contract:
forge create Create2Factory -r http://127.0.0.1:8545 --broadcast --private-key $DEPLOYER_PRIVATE_KEY --constructor-args $DEPLOYER_ADDRESS
DEPLOYER_PRIVATE_KEY
: Any key from anvil pre-funded addresses.DEPLOYER_ADDRESS
: This address should match the $DEPLOYER_ADDRESS in.env
Add the deployed Create2Factory contract address to your .env
file under the variable CREATE2_FACTORY_ADDRESS
.
Follow the instructions in evm-cctp-contracts-private README to deploy Create2Factory. Update DEPLOYER_ADDRESS
and CREATE2_FACTORY_ADDRESS
in .env
.
Run the following command to generate deployment transactions for GatewayWallet
and GatewayMinter
:
ENV=$ENV forge script script/001_DeployGatewayWallet.sol --rpc-url $RPC_URL -vvvv --slow --force
ENV=$ENV forge script script/001_DeployGatewayMinter.sol --rpc-url $RPC_URL -vvvv --slow --force
ENV
: UseSMOKEBOX
for local and SMOKEBOX deployment. Or choose fromSANDBOX
andPROD
.RPC_URL
: The rpc url for the targeted blockchain. usehttp://127.0.0.1:8485
for local deployment.
The generated transaction data will be available in the broadcast/
directory and can be used for signing.
Fill in the Deployed Contract Validation
section in .env
and run:
forge script script/003_DeployedContractValidation.s.sol --rpc-url $RPC_URL -vvvv --slow --force
This command validates deployed contract bytecode matches expected bytecode and contract state matches expected values.
Run the following command to generate new artifacts if openzeppelin-contracts
submodule is updated. Current commit hash is acd4ff7
.
forge build lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol --force
cp out/ERC1967Proxy.sol/ERC1967Proxy.json script/compiled-contract-artifacts/ERC1967Proxy.json
Run the following command to generate new artifacts for Gateway smart contracts.
forge build src/UpgradeablePlaceholder.sol --force
cp out/UpgradeablePlaceholder.sol/UpgradeablePlaceholder.json script/compiled-contract-artifacts/UpgradeablePlaceholder.json
forge build src/GatewayMinter.sol --force
cp out/GatewayMinter.sol/GatewayMinter.json script/compiled-contract-artifacts/GatewayMinter.json
forge build src/GatewayWallet.sol --force
cp out/GatewayWallet.sol/GatewayWallet.json script/compiled-contract-artifacts/GatewayWallet.json
Find salts that creates gas-efficient proxy addresses via:
cast create2 --starts-with $ADDRESS_PREFIX --deployer $DEPLOYER> --init-code-hash $INIT_CODE_HASH
ADDRESS_PREFIX
is the prefix of the address we want to find. Usually set to00000000
for a gas-efficient address.DEPLOYER
is the address of Create2Factory.INIT_CODE_HASH
is keccak256 hash of initcode + abi-encoded constuctor argument.
To run tests using Foundry, run yarn test
. This will run all tests using the default Anvil localnet.
To run tests against each supported network (by forking from each network's RPC endpoint), run yarn test:all
. If failures related to remote state from an old block are encountered, either point to archive nodes or run ./scripts/update_block_numbers.sh
to pin the latest block for each network and try again.
To run tests and output a gas report for the top-level contracts, run yarn test:gas
.
To simplify local development and testing we have a local port of the FiatToken contracts from the https://github.com/circlefin/stablecoin-evm repo. The port is based on commit 0642db6. When there are essential changes to the FiatToken contracts (e.g., new version release), we'll need to:
- Go through the diff between the above commit and the latest version, applying the latest changes into
test/mock_fiattoken
- Update dependency imports and relative imports
- Bump solidity version and fix resulting compiler errors
- Update
test/util/DeployMockFiatToken.sol
if necessary
Run yarn lint
to lint all .sol
files in the src
and test
directories, and yarn lint:fix
to automatically fix any fixable linting errors.
Run yarn format
to check the formatting of all .sol
files in the src
and test
directories, and yarn format:fix
to automatically format them.
Run yarn coverage
to generate a coverage report for the tests. This depends on the lcov
and genhtml
commands, which may be installed on macOS with brew install lcov
. The coverage report will be generated in the coverage
directory.
To check the bytecode size of all top-level contracts against the EIP-170 contract size limit, run yarn sizes
.
This project relies heavily on the TypedMemView
library (lib/memview-sol/
) for efficient memory manipulation.
Warning: As documented in the TypedMemView library itself, it utilizes unallocated memory operations and does not guarantee cleanup of unallocated memory regions after its internal functions execute.
Implication: This means that memory subsequently allocated by contracts in this project (e.g., declaring new memory
variables like arrays or structs after TypedMemView
operations have occurred within the same transaction execution path) might not be zero-initialized. It could contain residual data from previous operations.
Required Precaution: Developers working on this codebase must not assume that newly allocated memory variables or structures are automatically zero-initialized. If the logic relies on a memory variable starting at zero (or false
, address(0)
, etc.), it must be explicitly initialized after allocation.
We use Github actions to run the linter and all the tests. The workflow configuration can be found in .github/workflows/pipeline.yml. While not a complete replacement, all CI steps may be run locally with yarn ci
.
You can manually trigger the Olympix.ai Code Scanning workflow using the workflow_dispatch
feature of GitHub Actions.
- Click on the
Actions
tab. - In the left sidebar, select
Olympix Scan
. - Select the branch & click on the
Run workflow
button.