# Build a Bitcoin Name System

Let's build the Bitcoin Name System (BNS), a decentralized, open, and permissionless naming system on Bitcoin.

* buy and sell BNS name
* register a human-readable name like 'alice.tc' or 'bob.sat'
* map a human-readable name like 'bob.sat' to a machine-readable id like a Bitcoin address

## Write the BNS smart contract

It turns out that writing the Bitcoin Name System smart contract is very simple. Here is a basic contract to provide a DNS-like naming system on Bitcoin Virtual Machine.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract BNS is ERC721 {

        using Counters for Counters.Counter;
        Counters.Counter private _tokenIds;

        mapping(bytes => uint256) public registry;
        mapping(bytes => bool) public registered;

        mapping(uint256 => address) public resolver;

        constructor() ERC721("Bitcoin Name System", "BNS") {}

        function register(address owner, bytes memory name) 
                public 
                returns (uint256) 
        {
                require(!registered[name]);

                uint256 id = _tokenIds.current();
                _mint(owner, id);
                registry[name] = id;
                registered[name] = true;
                resolver[id] = owner;

                _tokenIds.increment();
                return id;
        }

        function map(uint256 tokenId, address to) public {
                require(msg.sender == ownerOf(tokenId));
                resolver[tokenId] = to;
        }
}
```

Extending ERC-721, we only need to implement the `register()` function to register a new name as an NFT and the `map()` function to map a human-readable name like 'bob.sat' to a machine-readable id like a wallet address.

Sending and receiving a BNS name is now as simple as sending and receiving an NFT. You can also trade the BNS name on open markets since it's an ERC-721.

## Clone the smart contract examples

We've prepared a few different examples for you to get started. The BNS example is located at **smart-contract-examples/contracts/BNS.sol**.

```bash
git clone https://github.com/trustlesscomputer/smart-contract-examples.git
```

## Compile the contracts

To compile your contracts, use the built-in `hardhat compile` task.

```bash
cd smart-contract-examples
npm install
npx hardhat compile
```

## Deploy the contracts

Review config file `hardhat.config.ts`. The network configs should look like this.

```js
  networks: {
    mynw: {
      url: "http://localhost:10002",
      accounts: {
        mnemonic: "<your mnemonic with funds>"
      },
      timeout: 100_000,
    },
    blockscoutVerify: {
      blockscoutURL: "http://localhost:4000", // your explorer URL
      ...
    }
  }
```

Run the deploy scripts using `hardhat-deploy`.

```bash
npx hardhat deploy --tags BNS
```

{% hint style="warning" %}
Make sure the accounts in hardhat.config.ts have some $BVM.
{% endhint %}

## Interact with the contracts

Once the contracts are deployed, you can interact with them. We've prepared a few `hardhat tasks` to make it easy for you to interact with the contracts.

```bash
# register a name
npx hardhat register --domain "bob.sat"

# create a mapping
npx hardhat map "bob.sat" <a-wallet-address>

# resolve a human-readable name to a machine-readable id
npx hardhat resolve --domain "bob.sat"
```

## Register your domain

```bash
git clone https://github.com/trustlesscomputer/smart-contract-examples
cd smart-contract-examples
npm install
npx hardhat compile
npx hardhat register --domain yourname.tc \
--contract 0x8b46F89BBA2B1c1f9eE196F43939476E79579798 \
--privatekey 0xafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafaf # your private key
```

This will output the transaction hash, which can be used to track its status via the [explorer](http://explorer.trustless.computer). After it is confirmed, you can try resolving that name by calling the BNS contract

```bash
npx hardhat resolve --domain yourname.tc \
--contract 0x8b46F89BBA2B1c1f9eE196F43939476E79579798 \
```
