# Tutorial 1: Hello World

> Guided steps to get started with o1js, zkApps, and programming with zero knowledge proofs. Learn to code a zkApp from start to finish.

Canonical URL: https://docs.minaprotocol.com/zkapps/tutorials/hello-world

This Hello World tutorial helps you get started with o1js, zkApps, and programming with zero knowledge proofs.

In this step-by-step tutorial, you learn to code a zkApp from start to finish.

You will:

- Write a basic smart contract that stores a number as on-chain state.
- The contract logic allows this number to be replaced only by its square; for example, 3 -> 9 -> 81, and so on.
- Create a project using the [zkApp CLI](https://www.npmjs.com/package/zkapp-cli)
- Write your smart contract code
- Use a simulated local Mina blockchain to interact with your smart contract.

Later tutorials introduce more concepts and patterns.

The full source code for this tutorial is provided in the [examples/zkapps/01-hello-world](https://github.com/MinaProtocol/docs2/tree/main/examples/zkapps/01-hello-world) directory on GitHub. While you're there, give the `/docs2` repository a star so that other zk developers can learn to build a zkApp!

:::info

To prevent copying command prompts as shown in the examples, use the copy code to clipboard button that appears at the top right of the snippet box when you hover over it.

:::

## Prerequisites

Ensure your environment meets the [Prerequisites](/zkapps/tutorials#prerequisites) for zkApp Developer Tutorials.

In particular, make sure you have the zkApp CLI installed:

```sh
$ npm install -g zkapp-cli
```

## Create a new project

Now that you have the tooling installed, you can start building your application.

1. Create or change to a directory where you have write privileges.
1. Now, create a project using the `zk project` command:

  ```sh
  $ zk project 01-hello-world
  ```

  The `zk project` command has the ability to scaffold the UI for your project. For this tutorial, select `none`:

  ```sh
  ? Create an accompanying UI project too? …
    next
    svelte
    nuxt
    empty
  > none
  ```

  The expected output is:

  ```sh
  ✔ Create an accompanying UI project too? · none
  ✔ UI: Set up project
  ✔ Initialize Git repo
  ✔ Set up project
  ✔ NPM install
  ✔ NPM build contract
  ✔ Set project name
  ✔ Git init commit

  Success!

  Next steps:
    cd 01-hello-world
    git remote add origin <your-repo-url>
    git push -u origin main
  ```

  The `zk project` command creates the `01-hello-world` directory that contains the scaffolding for your project, including tools such as the Prettier code formatting tool, the ESLint static code analysis tool, and the Jest JavaScript testing framework.

1. Change into the `01-hello-world` directory and list the contents:

  ```sh
  $ cd 01-hello-world
  $ ls
  ```

  The output shows these results:

  ```sh
  LICENSE
  README.md
  babel.config.cjs
  build
  config.json
  jest-resolver.cjs
  jest.config.js
  keys
  node_modules
  package-lock.json
  package.json
  src
  tsconfig.json
  ```

For this tutorial, you run commands from the root of the `01-hello-world` directory as you work in the `src` directory on files that contain the TypeScript code for the smart contract. Each time you make updates, then build or deploy, the TypeScript code is compiled into JavaScript in the `build` directory.

### Prepare the project

Start by deleting the default files that come with the new project.

1. To delete the old files:

  ```sh
  $ rm src/Add.ts
  $ rm src/Add.test.ts
  $ rm src/interact.ts
  ```

1. Now, create the new files for your project:

  ```sh
  $ zk file src/Square
  $ touch src/main.ts
  ```

    - The `zk file` command created the `src/Square.ts` and `src/Square.test.ts` test files.
    - This tutorial does not include writing tests, so you just use the `main.ts` file as a script to interact with the smart contract and observe how it works.

    In later tutorials, you learn how to interact with a smart contract from the browser, like a typical end user.

1. Now, open `src/index.ts` in a text editor and change it to look like:

  ```ts title="src/index.ts"
  import { Square } from './Square.js';

  export { Square };
  ```

The `src/index.ts` file contains all of the exports you want to make available for consumption from outside your smart contract project, such as from a UI.

## Write the zkApp Smart Contract

Now, the fun part! Write your smart contract in the `src/Square.ts` file.

A final version of the smart contract is provided in the [Square.ts](https://github.com/MinaProtocol/docs2/blob/main/examples/zkapps/01-hello-world/src/Square.ts) example file. The code blocks on this page are taken from the example files when the docs are built, so they always match the code that CI runs.

This part of the tutorial walks you through the `Square` smart contract code already completed in the `src/Square.ts` example file.

### Copy the example

This tutorial describes each part of the completed code in the [Square.ts](https://github.com/MinaProtocol/docs2/blob/main/examples/zkapps/01-hello-world/src/Square.ts) example file.

1. First, open the [Square.ts](https://github.com/MinaProtocol/docs2/blob/main/examples/zkapps/01-hello-world/src/Square.ts) example file.

1. Copy the entire contents of the file into your smart contract in the `src/Square.ts` file.

Now you are ready to review the imports in the smart contract.

### Imports

The `import` statement brings in other packages and dependencies to use in your smart contract.

:::info

All functions used inside a smart contract must operate on o1js compatible data types: `Field` types and other types built on top of `Field` types.

:::

```ts title="src/Square.ts"
import { Field, SmartContract, state, State, method } from 'o1js';
```

These items are:

- `Field`: The native number type in o1js. You can think of field elements as unsigned integers. Field elements are the most basic type in o1js. All other o1js-compatible types are built on top of field elements.
- `SmartContract`: The class that creates zkApp smart contracts.
- `state`: A convenience decorator used in zkApp smart contracts to create references to state stored on-chain in a zkApp account.
- `State`: A class used in zkApp smart contracts to create state stored on-chain in a zkApp account.
- `method`: A convenience decorator used in zkApp smart contracts to create smart contract methods like functions. Methods that use this decorator are the end user's entry points to interacting with a smart contract.

### Smart contract class

Now, review the smart contract in the `src/Square.ts` file.

The smart contract called `Square` has one element of on-chain state named `num` of type `Field` as defined by following code:

```ts title="src/Square.ts"
export class Square extends SmartContract {
  @state(Field) num = State<Field>();
```

zkApps can have up to 32 fields of on-chain state. Each field stores up to 32 bytes (technically, 31.875 bytes or 255 bits) of arbitrary data. A later tutorial covers options for off-chain state.

Now, this code adds the `init` method to set up the initial state of the smart contract on deployment:

```ts title="src/Square.ts"
export class Square extends SmartContract {
  @state(Field) num = State<Field>();

  init() {
    super.init();
    this.num.set(Field(3));
  }
```

Since this code extends `SmartContract` that has its own initialization to perform, calling `super.init()` invokes this function on the base class.

Then, `this.num.set(Field(3))` initializes the on-chain state `num` to a value of `3`.

You can optionally specify permissions. See [setPermissions](https://docs.o1labs.org/o1js/api-reference/classes/SmartContract) in the o1js Reference documentation.

Finally, this code adds the `update()` function:

```ts title="src/Square.ts"
  @method async update(square: Field) {
    const currentState = this.num.get();
    this.num.requireEquals(currentState);
    square.assertEquals(currentState.mul(currentState));
    this.num.set(square);
  }
}
```

The function name `update` is arbitrary, but it makes sense for this example. Notice how the `@method` decorator is used because it is intended to be invoked by end users by using a zkApp UI, or as in this case, the `main.ts` script.

This method contains the logic by which end users are allowed to update the zkApp's account state on chain.

A zkApp account is an account on the Mina blockchain where a zkApp smart contract is deployed. A zkApp account has a verification key associated with it.

In this example, the code specifies:

- If the user provides a number (for example, 9) to the `update()` method that is the square of the existing on-chain state referred to as `num` (for example, 3), then update the `num` value that is stored on-chain to the provided value (in this case, 9).
- If the user provides a number that does not meet these conditions, they are unable to generate a proof or update the on-chain state.

These update conditions are accomplished by using assertions within the method. When a user invokes a method on a smart contract, all assertions must be true to generate the zero knowledge proof from that smart contract. The Mina network accepts the transaction and updates the on-chain state only if the attached proof is valid. This assertion is how you can achieve predictable behavior in an off-chain execution model.

Notice that `get()` and `set()` methods are used for retrieving and setting on-chain state.

- A smart contract retrieves the on-chain account state when it is first invoked if at least one `get()` exists within it.

- Similarly, using `set()` changes the transaction to indicate that changes to this particular on-chain state are updated only when the transaction is received by the Mina network if it contains a valid authorization (usually, a valid authorization is a proof).

The logic also uses the `.mul()` method for multiplication of the values stored in `Field` types. You can view all available [methods](https://docs.o1labs.org/o1js/api-reference/classes/Field#methods) in the o1js Reference documentation.

You remember that functions in your smart contract must operate on o1js compatible data types: `Field` types and other types built on top of `Field` types. Because a smart contract is really a zero knowledge circuit, functions from random npm packages work inside a smart contract only if the functions the contract provides operate on o1js-compatible data types.

Importantly, data passed as an input to a smart contract method in o1js is private and never seen by the network.

You can also store data publicly on-chain when needed, like `num` in this example. A later tutorial covers an example that leverages privacy.

Congratulations, you have reviewed the complete smart contract code.

## Interact with a smart contract

Next, write a script that interacts with your smart contract. As before, the complete [main.ts](https://github.com/MinaProtocol/docs2/blob/main/examples/zkapps/01-hello-world/src/main.ts) example file is provided. Follow these steps to build the `main.ts` file so you can interact with the smart contract.

### Imports

For this tutorial, the `import` statement brings in items from `o1js` that you use to interact with your smart contract.

1. Copy the following lines from [main.ts](https://github.com/MinaProtocol/docs2/blob/main/examples/zkapps/01-hello-world/src/main.ts) example file into the `src/main.ts` file:

  ```ts title="src/main.ts"
  import { Square } from './Square.js';
  import { Field, Mina, PrivateKey, AccountUpdate } from 'o1js';
  ```

  These import items are:

    - `Field`: The same o1js unsigned integer type that you learned earlier.
    - `Mina`: A simulated local Mina blockchain to deploy the smart contract to so you can interact with it as a user would.
    - `PrivateKey`: A class with functions for manipulating private keys.
    - `AccountUpdate`: A class that generates a data structure that can update zkApp accounts.

### Simulated Local Blockchain

Using a simulated local blockchain speeds up development and tests the behavior of your smart contract locally. Later tutorials cover how to use a lightweight Mina network (Lightnet) to test your zkApp before you deploy to live networks.

:::info

- The term _simulated local blockchain_ refers to the local testing blockchain you use in the first phase of testing as described here.
- The term _Lightnet_ is used to describe the lightweight Mina network (Lightnet) that is a more accurate representation of the Mina blockchain. See [Testing zkApps with Lightnet](/zkapps/writing-a-zkapp/introduction-to-zkapps/testing-zkapps-lightnet).

:::

To initialize your simulated local blockchain, add the following code from the [main.ts](https://github.com/MinaProtocol/docs2/blob/main/examples/zkapps/01-hello-world/src/main.ts) example file to `src/main.ts`:

```ts title="src/main.ts"
const useProof = false;

const Local = await Mina.LocalBlockchain({ proofsEnabled: useProof });
Mina.setActiveInstance(Local);

const deployerAccount = Local.testAccounts[0];
const deployerKey = deployerAccount.key;
const senderAccount = Local.testAccounts[1];
const senderKey = senderAccount.key;
```

This simulated local blockchain provides pre-funded accounts. Add these lines to create local test accounts with test MINA (tMINA) to use for this tutorial:

```ts title="src/main.ts"
// ----------------------------------------------------

// Create a public/private key pair. The public key is your address and where you deploy the zkApp to
const zkAppPrivateKey = PrivateKey.random();
const zkAppAddress = zkAppPrivateKey.toPublicKey();
```

### Build and run the smart contract

Now that the Square smart contract is complete, these commands run your project as a simulated local blockchain.

To compile the TypeScript code into JavaScript:

```sh
$ npm run build
```

To run the JavaScript code:

```sh
$ node build/src/main.js
```

You have the option to combine these commands into one line:

```
npm run build && node build/src/main.js
```

- The `npm run build` command creates JavaScript code in the `build` directory.
- The `&&` operator links two commands together. The second command runs only if the first command is successful.
- The `node build/src/main.js` command runs the code in `src/main.ts`.

### Initialize your smart contract

To initialize your smart contract, add more code from the [main.ts](https://github.com/MinaProtocol/docs2/blob/main/examples/zkapps/01-hello-world/src/main.ts) example file to the `src/main.ts` file.

All smart contracts that you create with the zkApp CLI use similar code:

- Create a public/private key pair; the public key is an address on the Mina network where you deploy the zkApp to
- Create an instance of your smart contract `Square` and deploy it to `zkAppAddress`
- Get the initial state of `Square` after deployment

Comments break down each stage:

```ts title="src/main.ts"
// create an instance of Square - and deploy it to zkAppAddress
const zkAppInstance = new Square(zkAppAddress);
const deployTxn = await Mina.transaction(deployerAccount, async () => {
  // 1 Mina fee is required to create a new account for the zkApp
  // This line means the deployer account will pay the fee for any account created in this transaction
  AccountUpdate.fundNewAccount(deployerAccount);
  await zkAppInstance.deploy();
});
await deployTxn.sign([deployerKey, zkAppPrivateKey]).send();

// get the initial state of Square after deployment
const num0 = zkAppInstance.num.get();
console.log('state after init:', num0.toString());
```

Try running this command again:

```sh
$ npm run build && node build/src/main.js
```

The expected output is:

```sh
> 01-hello-world@0.1.0 build
> tsc

state after init: 3
```

### Update your zkApp account with a transaction

To update your local zkApp account with a transaction, add the following code to the `src/main.ts` file:

```ts title="src/main.ts"
// ----------------------------------------------------

const txn1 = await Mina.transaction(senderAccount, async () => {
  await zkAppInstance.update(Field(9));
});
await txn1.prove();
await txn1.sign([senderKey]).send();

const num1 = zkAppInstance.num.get();
console.log('state after txn1:', num1.toString());
```

This code creates a new transaction that attempts to update the field to the value `9`. Because of the rules in the `update()` function that is called on the smart contract, this command succeeds when you run it again:

```sh
$ npm run build && node build/src/main.js
```

The expected output is:

```sh
> 01-hello-world@0.1.0 build
> tsc

state after init: 3
state after txn1: 9
```

### Add a transaction that fails

It's time to do some testing. To add a transaction that fails, add more code from the [main.ts](https://github.com/MinaProtocol/docs2/blob/main/examples/zkapps/01-hello-world/src/main.ts) example file to the `src/main.ts` file.

The contract logic allows the number that is stored as on-chain state to be replaced only by its square. Now that `num` is in state `9`, updating is possible only with `81`.

To test a failure, add these next lines of code from the `src/main.ts` example file. They try to change the state to `75` with `zkAppInstance.update(Field(75))`:

```ts title="src/main.ts"
// ----------------------------------------------------

try {
  const txn2 = await Mina.transaction(senderAccount, async () => {
    await zkAppInstance.update(Field(75));
  });
  await txn2.prove();
  await txn2.sign([senderKey]).send();
} catch (error: any) {
  console.log(error.message);
}
const num2 = zkAppInstance.num.get();
console.log('state after txn2:', num2.toString());
```

Try running this command again:

```sh
$ npm run build && node build/src/main.js
```

The expected output is:

```sh
> 01-hello-world@0.1.0 build
> tsc

state after init: 3
state after txn1: 9
Field.assertEquals(): 75 != 81
state after txn2: 9
```

And finally, add a third transaction that makes the correct update: it changes the state to `81` with `zkAppInstance.update(Field(81))`:

```ts title="src/main.ts"
// ----------------------------------------------------

const txn3 = await Mina.transaction(senderAccount, async () => {
  await zkAppInstance.update(Field(81));
});
await txn3.prove();
await txn3.sign([senderKey]).send();

const num3 = zkAppInstance.num.get();
console.log('state after txn3:', num3.toString());
```

Run this command again:

```sh
$ npm run build && node build/src/main.js
```

The expected output is:

```sh
> 01-hello-world@0.1.0 build
> tsc

state after init: 3
state after txn1: 9
Field.assertEquals(): 75 != 81
state after txn2: 9
state after txn3: 81
```

## Test it

Printing the state and reading the numbers is how you check the contract by
hand. A test suite checks the same thing on every change, without you reading
anything. The example project in this repository carries one:

```sh
cd examples/zkapps/01-hello-world
npm install
npm test
```

It asserts what this page just showed you: the state starts at `3`, an update
to `9` is accepted, an update to `75` is **rejected** with
`Field.assertEquals(): 75 != 81` and leaves the state at `9`, and an update to
`81` is accepted after it.

The rejection matters as much as the two successes. A contract that accepted
`75` would still print three lines and still look like it worked.

## Follow along

You can follow along in this video as cryptographer, David Wong, learns how to code a Hello World project.


The video is provided for educational purposes and uses earlier versions of the zkApp CLI and o1js, so there are some differences. The Hello World tutorial always uses the most recent version of the zkApp CLI and o1js.

## Conclusion

Congratulations! You have successfully completed all of the steps to build your first zkApp with o1js.

Check out [Tutorial 2: Private Inputs and Hash Functions](private-inputs-hash-functions) to learn how to use private inputs and hash functions with o1js.

Find more tutorials and resources in the [zkApps docs](/zkapps/writing-a-zkapp).
