# BFS: Build an IPFS alternative

Let's build the Bitcoin File System (BFS), a decentralized, open, and permissionless file storage on Bitcoin.

* write a file to Bitcoin
* read a file from Bitcoin
* support large files

## Write the BFS smart contract

It turns out that writing the Bitcoin File System smart contract is very simple. Here is a basic contract to provide decentralized file storage on Bitcoin Virtual Machine.

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

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

error FileExists();

contract BFS {
        using Counters for Counters.Counter;
        Counters.Counter private idCounter;
        mapping(address => mapping(string => mapping(uint256 => bytes))) public dataStorage;
        mapping(address => mapping(string => uint256)) public chunks; // max chunk index
        mapping(address => mapping(string => uint256)) public bfsId;

        constructor () {
                idCounter.increment(); // start from 1
        }

        function store(string memory filename, uint256 chunkIndex, bytes memory _data) external {
                if (dataStorage[msg.sender][filename][chunkIndex].length > 0) {
                        revert FileExists();
                }
                dataStorage[msg.sender][filename][chunkIndex] = _data;
                if (chunks[msg.sender][filename] < chunkIndex) {
                        chunks[msg.sender][filename] = chunkIndex;
                }
                bfsId[msg.sender][filename] = idCounter.current();
                idCounter.increment();
        }

        function load(address addr, string memory filename, uint256 chunkIndex) public view returns (bytes memory, int256) {
                uint256 temp = chunkIndex + 1;
                int256 nextChunk = (temp > chunks[addr][filename]) ? -1 : int256(temp);
                return (dataStorage[addr][filename][chunkIndex], nextChunk);
        }

        function count(address addr, string memory filename) public view returns (uint256) {
                return chunks[addr][filename];
        }

        function getId(address addr, string memory filename) public view returns (uint256) {
                return bfsId[addr][filename];
        }
}
```

The `store()` function saves a chunk of a file. The `load()` function returns the data of a specific chunk. And the `getId()` function returns the ID of the file.

You can save a large file onto Bitcoin by splitting it into smaller chunks, committing them to Bitcoin, and retrieving & merging them back as needed.

BFS files are immutable.

## 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 BFS
```

{% 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
# store data
echo "this is some text" > data.txt
npx hardhat write-storage --filename ./data.txt
npx hardhat read-storage --filename ./data.txt # read data, print it as readable text
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bvm.network/bvm/bitcoin-dapps/evm-code-tutorials/bfs-build-an-ipfs-alternative.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
