Quickstart For Developers

This quickstart is for web developers who want to start building decentralized applications (dApps) using Camelot. It makes no assumptions about your prior experience with Ethereum or Solidity. Familiarity with Javascript and yarn is expected. If you're new to Ethereum, consider studying the Ethereum documentation before proceeding.

A.How to Write a contract

We're going to build a digital cupcake vending machine using Solidity smart contracts. Our vending machine will follow two rules:

1. The vending machine will distribute a cupcake to anyone who hasn't recently received one.

2. The vending machine's rules can't be changed by anyone.

Here's our vending machine implemented as a Javascript class:

VendingMachine.js

class VendingMachine {
  // state variables = internal memory of the vending machine
  cupcakeBalances = {};
  cupcakeDistributionTimes = {};

  // Vend a cupcake to the caller
  giveCupcakeTo(userId) {
    if (this.cupcakeDistributionTimes[userId] === undefined) {
      this.cupcakeBalances[userId] = 0;
      this.cupcakeDistributionTimes[userId] = 0;
    }

    // Rule 1: The vending machine will distribute a cupcake to anyone who hasn't recently received one.
    const fiveSeconds = 5000;
    const userCanReceiveCupcake = this.cupcakeDistributionTimes[userId] + fiveSeconds <= Date.now();
    if (userCanReceiveCupcake) {
      this.cupcakeBalances[userId]++;
      this.cupcakeDistributionTimes[userId] = Date.now();
      console.log(`Enjoy your cupcake, ${userId}!`);
      return true;
    } else {
      console.error(
        'HTTP 429: Too Many Cupcakes (you must wait at least 5 seconds between cupcakes)',
      );
      return false;
    }
  }

  getCupcakeBalanceFor(userId) {
    return this.cupcakeBalances[userId];
  }
}

The VendingMachine class uses state variables and functions to implement predefined rules. This implementation is useful because it automates cupcake distribution, but there's a problem: it's hosted by a centralized server controlled by a third-party service provider.

Let's decentralize our vending machine's business logic and data by porting the above Javascript implementation into a Solidity smart contract.

Create a decentralized-cupcakes directory for your project and install hardhat using VS Code's integrated terminal:

mkdir decentralized-cupcakes
cd decentralized-cupcakes 
yarn init -y 
yarn add hardhat @nomicfoundation/hardhat-toolbox -D

This installs two packages: hardhat lets us write, test and deploy our smart contracts, and hardhat-toolbox is a bundle of popular Hardhat plugins that we'll use later.

Next, run yarn hardhat init to configure Hardhat. Select Create a JavaScript project when prompted. Make sure you specify your decentralized-cupcakes directory as the project root when asked.

At this point, you should see the following items (among others) in your decentralized-cupcakes project directory:

Replace the contents of hardhat.config.js with the following:

require('@nomicfoundation/hardhat-toolbox');

// NEVER record important private keys in your code - this is for demo purposes
const CAMELOT_TESTNET_PRIVATE_KEY = '';
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  solidity: '0.8.18',
  networks: {
    hardhat: {
      chainId: 52001,
    },
    camelot-testnet: {
      url: 'https://testnet-rpc.cam3lot.io',
      //accounts: [CAMELOT_MAINNET_TEMPORARY_PRIVATE_KEY]
    },
  },
};

Before compiling the default contracts, you will need to install additional dependencies. Run yarn hardhat compile and expect it to fail for the first time — follow those instructions, then run yarn hardhat compile again until it runs successfully. You should see Compiled 1 Solidity file successfully in the terminal output. You should also see a new decentralized-cupcakes/artifacts/ directory. This directory contains the compiled smart contract.

Open scripts/deploy.js and replace its contents with the following:

scripts/deploy.js
const hre = require('hardhat');

async function main() {
  const vendingMachine = await hre.ethers.deployContract('VendingMachine');
  await vendingMachine.waitForDeployment();
  console.log(`Cupcake vending machine deployed to ${vendingMachine.target}`);
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});

We'll use this to deploy our smart contract in a moment. Next, delete contracts/Lock.sol and replace it with contracts/VendingMachine.sol, the smarter alternative to our Javascript implementation:

VendingMachine.sol
pragma solidity ^0.8.9;

// Rule 2: The vending machine's rules can't be changed by anyone.
contract VendingMachine {
    // state variables = internal memory of the vending machine
    mapping(address => uint) private _cupcakeBalances;
    mapping(address => uint) private _cupcakeDistributionTimes;

    function giveCupcakeTo(address userAddress) public returns (bool) {
        // this code is unnecessary, but we're keeping it here so you can compare it to the JS implementation
        if (_cupcakeDistributionTimes[userAddress] == 0) {
            _cupcakeBalances[userAddress] = 0;
            _cupcakeDistributionTimes[userAddress] = 0;
        }

        // Rule 1: The vending machine will distribute a cupcake to anyone who hasn't recently received one.
        uint fiveSecondsFromLastDistribution = _cupcakeDistributionTimes[userAddress] + 5 seconds;
        bool userCanReceiveCupcake = fiveSecondsFromLastDistribution <= block.timestamp;
        if (userCanReceiveCupcake) {
            _cupcakeBalances[userAddress]++;
            _cupcakeDistributionTimes[userAddress] = block.timestamp;
            return true;
        } else {
            revert("HTTP 429: Too Many Cupcakes (you must wait at least 5 seconds between cupcakes)");
        }
    }

    // Getter function for the cupcake balance of a user
    function getCupcakeBalanceFor(address userAddress) public view returns (uint) {
        return _cupcakeBalances[userAddress];
    }
}

Note that this smart contract is written in Solidity, a language that compiles to EVM bytecode. This means that it can be deployed to any Ethereum-compatible blockchain, including Ethereum mainnet, Arbitrum One, and Arbitrum Nova.

Run yarn hardhat compile again. You should see Compiled 1 Solidity file successfully in the terminal output. You should also see a new decentralized-cupcakes/artifacts/contracts/VendingMachine.sol directory.

B.How to Depoly a contract to the Camelot testnet

We were able to deploy to a local testnet for free because we were using Hardhat's built-in Ethereum network emulator. Camelot's testnet is powered by a real network of real nodes, so we'll need to pay a small transaction fee to deploy our smart contract. This fee can be paid with the Camelot’s testnet's token, $BTC.

First, update the hardhat.config.js file to specify the private key of the test account that you'll use to deploy your smart contract (and pay the transaction fee):

hardhat.config.js
// ...
const CAMELOT_TESTNET_PRIVATE_KEY = ''; // <- this should **not** begin with "0x"
// ...
accounts: [CAMELOT_TESTNET_PRIVATE_KEY]; // <- uncomment this line
// ...

Next, let's deposit some $BTC into the wallet corresponding to the private key we added to hardhat.config.js.

Once you've acquired some $BTC, you'll be able to deploy your smart contract to Camelot’s testnet by issuing the following command:

yarn hardhat run scripts/deploy.js --network CamelotTestnet

Cupcake vending machine deployed to 0x...

Congratulations! You've just deployed business logic and data to Camelot Testnet.

To view your smart contract in a blockchain explorer, visit

https://testnet-scan.cam3lot.io

C.RPC endpoints

Camelot is EVM compatible, you can connect to Camelot via your familiar EVM wallet as usual.

Here is the public RPC endpoints you can use:

Mainnet(Coming Soon)

Testnet

Network name: Camelot Testnet

RPC URL: https://testnet-rpc.cam3lot.io

Chain ID: 52001

Currency symbol: BTC

Block explorer URL: https://testnet-scan.cam3lot.io

Last updated