Account Authorization using Soroban AssemblyScript SDK
Tags: soroban, stellar, assemblyscript, smartcontract
Published: 2023-03-30 21:17:18

Hi! In my previous posts, i already covered many things such as storing data, logging contract, and defining error code. In this post I will take it to the next level, authorization. Authorization is one of security measure used in smart contracts, it can be used to various things such as allowing specific verified users to call a function, allowing specific users access stored data, and many more.

In this post i will explain Account authorization smart contract example that implements authorization control and updating account values stored in chain state.

##The Contract Code
The contract code will be similar to my previous post with additional code to do account authorization. Let's dive into the code:
```TypeScript
import {AddressObject, MapObject, RawVal, fromU32, toU32} from 'as-soroban-sdk/lib/value';
import {Map} from 'as-soroban-sdk/lib/map';
import * as ledger from 'as-soroban-sdk/lib/ledger';
import * as address from 'as-soroban-sdk/lib/address';
```
In this section, we import the necessary modules from the as-`soroban-sdk` library. The ledger module provides functions for interacting with the blockchain's storage. The `RawVal`, `toU32`, `fromU32`, `AddressObject`, and `MapObject` type is imported from the value module. `Map` imported from map module to act as stored data format. ledger and address module imported for any operation regarding ledger dan address operations.

```TypeScript
export function increment(user: AddressObject, value: RawVal): MapObject {

  address.requireAuth(user);
  var counter = 0;
  
  if (ledger.hasData(user)) {
    let dataValue = ledger.getData(user);
    counter = toU32(dataValue);
  }

  counter += toU32(value);
  let counterVal = fromU32(counter);
  ledger.putData(user, counterVal);

  let map = new Map();
  map.put(user, counterVal);

  return map.getHostObject();
}
```
The purpose of this function is to increment a counter associated with a given user's address in the Soroban ledger. The `address.requireAuth(user)` call at the beginning of the function ensures that the user has authorized the transaction before it can proceed.

The next block of code checks whether the user already has data associated with their address in the ledger using the `ledger.hasData(user)` function. If the user has data, it retrieves the current value of the counter using `ledger.getData(user)` and converts it to a 32-bit unsigned integer using the `toU32` function. If the user does not have data, the counter is initialized to zero.

The counter variable is then incremented by the value of value, which is also converted to a 32-bit unsigned integer using `toU32`. The updated value of counter is then converted back to a RawVal value using `fromU32` and stored in the ledger using the `ledger.putData(user, counterVal)` function.

Finally, a new `Map` is created and the updated counter value is added to it using `map.put(user, counterVal)`. The Map is then returned as a `MapObject`using `map.getHostObject()`.

Next, create `contract.json` file in your project directory, this file contains metadata for the contract.

```json
{
    "name": "Store and Retrieve Data Contract (Account Auth)",
    "version": "0.1.0",
    "description": "example",
    "host_functions_version": 29,
    "functions": [
        {
            "name" : "increment",
            "arguments": [
                {"name": "user", "type": "address"},
                {"name": "value", "type": "u32"}
            ],
            "returns" : "map[address, u32]"
        }
    ]
}
```

Before compiling the contract, we need to edit the `asconfig.json` file of your project. Replace its content with the following:

```json
{
  "extends": "as-soroban-sdk/sdkasconfig",
  "targets": {
    "release": {
      "outFile": "build/release.wasm",
      "textFile": "build/release.wat"
    },
    "debug": {
      "outFile": "build/debug.wasm",
      "textFile": "build/debug.wat"
    }
  }
}
```
The `asconfig.json` file is used by the AssemblyScript compiler (asc) to define the configuration for your project.


##Compiling the Contract
You need to compile it into WebAssembly first. To do this, you'll use the following command :

```
npx asc assembly/index.ts --target release
```
Now you should see two new files in the build/ directory: `release.wasm` and `release.wat`. 

We will use 2 different account to invoke this contract.Let's run the contract to see if it's works, we're gonna run the contract using `soroban-cli` on sandbox using the following command :

```bash
soroban contract invoke \
    --account GABGWMODVCF3VQS5BYCJBWMJUIS466Q3WT3AKGZZAKLBW2NYHIWOEYQT \
    --id 1 \
    --wasm build/release.wasm \
    --fn increment \
    -- \
    --user GABGWMODVCF3VQS5BYCJBWMJUIS466Q3WT3AKGZZAKLBW2NYHIWOEYQT \
    --value 10
```
You can run it a couple of times with any desired `--value`. And invoke the function using another account :
```bash
soroban contract invoke \
    --account GBYXXOAIKZJHZKGR4W7ERYWLAJDEYIPQJNETH6FGFIJUUB4PBVPISTNL \
    --id 1 \
    --wasm build/release.wasm \
    --fn increment \
    -- \
    --user GBYXXOAIKZJHZKGR4W7ERYWLAJDEYIPQJNETH6FGFIJUUB4PBVPISTNL \
    --value 5
```
And after couple of times invoking the function with 2 different accounts, you can check all stored data on that contract using this command:
```bash
soroban contract read --id 1
```
You should get similar output to:
```
"""GABGWMODVCF3VQS5BYCJBWMJUIS466Q3WT3AKGZZAKLBW2NYHIWOEYQT""",15
"""GBYXXOAIKZJHZKGR4W7ERYWLAJDEYIPQJNETH6FGFIJUUB4PBVPISTNL""",25
```

![Contract Storage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cxxczd5edwxvjkmwvxbt.png)

##Closing
Overall, this code provides a simple example of how Account Authorization works using the AssemblyScript SDK. By using the `address.requireAuth` and `address.requireAuthForArgs` functions, this code ensures that only authorized users can modify the counter associated with their address. Happy Sorobaning!