Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Arc is an open EVM-compatible layer 1 built on [Malachite](https://github.com/ci

- 🚀 **[Execution](crates/node/README.md)** - Execution binary and configuration
- 🗳️ **[Consensus](crates/malachite-app/README.md)** - Consensus binary and configuration
- 🧱 **[Contract deployment](docs/deploying-contracts.md)** - Arc Testnet network, compiler, and verification settings
- More: see Arc [developer docs](https://docs.arc.network/arc/concepts/welcome-to-arc) for guides, APIs, and specs

## Install and Run a Node
Expand Down
189 changes: 189 additions & 0 deletions docs/deploying-contracts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# Deploying Solidity contracts on Arc

Arc is EVM-compatible, but developer tooling should be configured with the Arc
network parameters explicitly. This page covers the settings that are most often
needed when deploying contracts to Arc Testnet.

## Arc Testnet network parameters

```ts
const arcTestnet = {
chainId: 5042002,
chainName: "Arc Testnet",
nativeCurrency: {
name: "USDC",
symbol: "USDC",
decimals: 18,
},
rpcUrls: ["https://rpc.testnet.arc.network"],
blockExplorerUrls: ["https://testnet.arcscan.app"],
};
```

## Solidity compiler target

When compiling contracts for Arc Testnet, target the Paris EVM unless your
contract stack has confirmed support for newer EVM opcodes on the target Arc
network.

Solidity 0.8.20 and later can emit the Shanghai `PUSH0` opcode by default.
Using `evmVersion: "paris"` avoids emitting `PUSH0` and keeps bytecode
compatible with pre-Shanghai EVM targets.

Hardhat example:

```ts
import type { HardhatUserConfig } from "hardhat/config";

const config: HardhatUserConfig = {
solidity: {
version: "0.8.24",
settings: {
optimizer: { enabled: true, runs: 200 },
evmVersion: "paris",
},
},
networks: {
arcTestnet: {
url: "https://rpc.testnet.arc.network",
chainId: 5042002,
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
},
},
};

export default config;
```

Foundry example:

```toml
# foundry.toml
[profile.default]
solc = "0.8.20"
evm_version = "paris"
optimizer = true
optimizer_runs = 200
# Uncomment only if your contract hits Solidity's stack-depth limit.
# This can significantly increase compile time.
# via_ir = true

[rpc_endpoints]
arc_testnet = "https://rpc.testnet.arc.network"
```

Deploy with:

```bash
forge script script/Deploy.s.sol:Deploy \
--rpc-url https://rpc.testnet.arc.network \
--private-key "$DEPLOYER_PRIVATE_KEY" \
--broadcast \
--config-path foundry.toml
```

The deployer wallet needs Arc Testnet USDC for gas. Testnet USDC is available
from the [Circle faucet](https://faucet.circle.com).

## Hardhat contract verification on Arcscan

Arcscan is Blockscout-based. With `@nomicfoundation/hardhat-verify`, configure a
custom chain that points to the Arcscan API endpoint.

```ts
import "@nomicfoundation/hardhat-verify";
import type { HardhatUserConfig } from "hardhat/config";

const config: HardhatUserConfig = {
networks: {
arcTestnet: {
url: "https://rpc.testnet.arc.network",
chainId: 5042002,
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
},
},
etherscan: {
apiKey: {
arcTestnet: "empty",
},
customChains: [
{
network: "arcTestnet",
chainId: 5042002,
urls: {
apiURL: "https://testnet.arcscan.app/api",
browserURL: "https://testnet.arcscan.app",
},
},
],
},
sourcify: {
enabled: false,
},
};

export default config;
```

Then verify with constructor arguments as usual:

```bash
npx hardhat verify --network arcTestnet <contract-address> <constructor-args>
```

## Foundry contract verification on Arcscan

Foundry can verify directly against Arcscan's Blockscout API:

```bash
forge verify-contract \
--verifier blockscout \
--verifier-url "https://testnet.arcscan.app/api/" \
--compiler-version 0.8.20 \
--evm-version paris \
--chain 5042002 \
<contract-address> src/<Contract>.sol:<Contract>
```

For constructor arguments, pass ABI-encoded args:

```bash
forge verify-contract \
--verifier blockscout \
--verifier-url "https://testnet.arcscan.app/api/" \
--compiler-version 0.8.20 \
--evm-version paris \
--chain 5042002 \
--constructor-args "$(cast abi-encode 'constructor(address,address)' <arg1> <arg2>)" \
<contract-address> src/<Contract>.sol:<Contract>
```

Notes:

- Blockscout does not require a real Etherscan API key, but
`@nomicfoundation/hardhat-verify` still expects a non-empty string.
- Replace `0.8.20` with the Solidity compiler version used for the deployment.
The verification compiler version must match the build exactly.
- Keep the explorer URL as `https://testnet.arcscan.app` for wallet and dApp
transaction links.

## Common Arc Testnet references

| Item | Value |
| -------------------- | -------------------------------------------- |
| Chain ID | `5042002` (`0x4cef52`) |
| RPC | `https://rpc.testnet.arc.network` |
| Explorer | `https://testnet.arcscan.app` |
| Native USDC / gas | `0x3600000000000000000000000000000000000000` |
| EURC | `0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a` |
| CCTP domain | `26` |
| TokenMessengerV2 | `0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA` |
| MessageTransmitterV2 | `0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275` |

Native USDC uses 6 decimals through its ERC-20 interface for transfers,
allowances, and balances, but native gas accounting such as `eth_getBalance`
uses 18 decimals.

For explorer readability, contracts can expose an `owner` view such as
`address public owner`. Arcscan displays public variables in the contract view,
which can help operators identify deployed instances.