blockchain parameter in your request. Additionally, you can deploy to Mainnet
by swapping out the Testnet API key for a Mainnet API key. See the
Testnet vs Mainnet guide for more details.
Prerequisites
Before you begin, ensure that you:- Create a Developer Account and acquire an API key in the Console.
- Make sure to register your Entity Secret prior to this Quickstart.
Step 1: Project setup
Set up your local development environment and install the required dependencies.1.1 Set up a new project
Create a new directory, navigate to it and initialize a new project with default settings1.2 Install dependencies
In the project directory, install the required dependencies. This guide uses SDKs for Circle developer-controlled wallets and Contracts.Step 2: Create a wallet and fund it with testnet tokens
In this section, you will create a developer-controlled wallet with the SDK and fund it with testnet USDC to pay for the gas fees needed to deploy the smart contract. If you already have a developer-controlled wallet, skip to Step 3.2.1 Setup and run a create-wallet script
Import the developer-controlled wallets SDK and initialize the client. You will require your API key and Entity Secret for this. Note that your API key and Entity Secret are sensitive credentials. Do not commit them to Git or share them publicly. Store them securely in environment variables or a secrets manager.Developer-controlled wallets are created in a wallet set, which is the source from which individual wallet keys are derived.
2.3 Fund the wallet with test USDC
Obtain some testnet USDC for executing transactions like making transfers and paying gas fees for those transactions. Circle’s Testnet Faucet provides testnet USDC and can be used once per hour to obtain additional USDC.2.4 Check the wallet’s balance
You can check your wallet’s balance from the Developer Console or programmatically by making a request toGET /wallets/{id}/balances
with the wallet ID of the wallet you created.
Step 3: Compile a smart contract
In this section, you will compile and deploy a minimal smart contract for an onchain payment inbox using Contracts. Users pay by approving and depositing USDC, payments are recorded via events, and the owner can withdraw the accumulated balance.This contract is intentionally minimal and for learning purposes only. Smart
contracts that manage real funds typically require additional security
patterns, testing, and audits, and often rely on community-reviewed libraries
such as OpenZeppelin.
constructor(address _owner): Sets the treasury owner and the USDC token address at deploymentreceive() (payable): Transfers approved USDC from the caller into the contract and emitsPaymentReceived(sender, amount)withdraw(): Allows only the owner to withdraw the entire USDC balance; emitsFundsWithdrawn(to, amount)balance() (view): Returns the contract’s current USDC balance
3.1 Obtain ABI and bytecode from Remix IDE
- Open the Remix IDE.
- Create a new file in the contracts folder called
MerchantTreasury.sol.
- Copy and paste the Solidity code into the file, then click on the Compile
button.

- Navigate to the Solidity Compiler tab from the left sidebar. Under Contracts,
make sure MerchantTreasuryUSDC (Merchant Treasury.sol) is selected. You
should see the option to copy the ABI and Bytecode. These values will be used
in the next step.

- The compiler output is available under Compilation Details. For more information on the Solidity compiler’s outputs, see using the compiler.
- The Application Binary Interface (ABI) is the standard way to interact with contracts on an EVM from outside the blockchain and for contract-to-contract interaction.
Step 4: Deploy the smart contract
In this section, you will deploy the smart contract on Arc using the contract’s ABI and bytecode, which you have compiled in the previous step. Import and initialize the Contracts SDK, then copy the ABI JSON and raw bytecode over from Remix. Note that you need to append0x to the raw bytecode.
The constructorParameters correspond to the arguments encoded in the
contract’s deployment bytecode. Since different contracts define different
constructors, these parameters vary based on the specific contract you deployed.
For this specific example, the parameter is the wallet address of the owner of
the contract.
getContract from the SDK directly.