> ## Documentation Index
> Fetch the complete documentation index at: https://build.flashnet.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploying a contract

> Get an API key and deploy with standard EVM tooling

<Note>
  Contract deployment requires an allow-listed RPC key. Contact us at **[info@flashnet.xyz](mailto:info@flashnet.xyz)** to get one.
</Note>

Flashnet's public RPC is filtered to read methods. Writes go through intents, and contract deployment doesn't fit the intent shape (it isn't Spark-funded). So deployment lives behind its own auth surface: a keyed JSON-RPC URL you use with standard EVM tooling.

## Once you have a key

Your URL looks like this:

```
https://rpc.makebitcoingreatagain.dev/access/<your-key>
```

Treat it like an Alchemy or Infura endpoint. Reads and writes both pass through. Use it with hardhat, foundry, viem `WalletClient`, ethers, or anything that speaks JSON-RPC. The chain id is the same as the public RPC (`getNetworkInfo().execution.chainId`).

## Deploy with foundry

[foundry docs](https://book.getfoundry.sh/forge/deploying):

```bash theme={null}
forge create src/MyContract.sol:MyContract \
  --rpc-url $FLASHNET_RPC_URL \
  --private-key $DEPLOYER_KEY \
  --verify --verifier sourcify \
  --verifier-url https://explorer.makebitcoingreatagain.dev/api/
```

The `--verify --verifier sourcify --verifier-url` triple tells `forge create` to upload sources to Flashnet's Blockscout instance right after deployment, so block-explorer links resolve to verified source instead of bytecode.

## Deploy with hardhat

[hardhat docs](https://hardhat.org/hardhat-runner/docs/guides/deploying):

```typescript theme={null}
// hardhat.config.ts
networks: {
  flashnet: {
    url: process.env.FLASHNET_RPC_URL,
    accounts: [process.env.DEPLOYER_KEY!],
    chainId: 21022,
  },
},
sourcify: {
  enabled: true,
  apiUrl: "https://explorer.makebitcoingreatagain.dev/api/",
  browserUrl: "https://explorer.makebitcoingreatagain.dev/",
},
```

Then deploy and verify:

```bash theme={null}
npx hardhat ignition deploy ignition/modules/MyContract.ts --network flashnet
npx hardhat verify --network flashnet $DEPLOYED_ADDRESS
```

## Why this is gated

A few reasons:

* The public RPC is read-only by design. Most write paths use intents because they have to coordinate with Spark.
* Deployment doesn't have a Spark counterpart, so it has no intent representation.
* Gating it lets us track who's deploying what, allocate resources, and prevent the chain from filling with churn during the alpha.

If you have a use case the docs don't cover, email **[info@flashnet.xyz](mailto:info@flashnet.xyz)**. We can usually scope a key in a day.

## After deployment

Calls to your contract still go through intents from a user's wallet. The deployer key is for deployment only; once the contract is live, users interact with it via `ExecutionClient.execute(...)` with the contract's address as the `to` field. See [Executing transactions](/products/execution/executing) for the call pattern.
