Skip to content

Auditing Data

Introduction

STRATO offers the ability to easily track the history of any contract's data over time. This enables easy data auditing and traceability. While it is possible on any blockchain to view the history of a contract's state, STRATO makes it easy by integrating the functionality into its Cirrus API. Contract history can also be referred to as a contract's Audit Log, or Audit Trail, since it provides a log of previous data.

Contract history can be enabled/disabled during any transaction. History is toggled on a per-contract type basis, so if a contract-type's history is currently enabled, any new changes involving that contract type will be recorded. Similarly, when history is disabled, any new changes will not be recorded. When history is toggled on a contract during a transaction, the new history setting will be active during the same transaction.

Enabling Contract History

History is enabled by setting the history property within the transaction payload metadata object to the name of the contract(s) for which to enable history. By default, contract history is disabled.

  • history: string
    • The name of the contract for which to enable history.
      • SimpleStorage
    • A comma separated list of contracts for which to enable history.
      • SimpleStorage,MyContract

Example

curl -X POST \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
  "txs": [
    {
      "payload": {
        "contract": "SimpleStorage",
        "src": "<contract-src>",
        "args": {
          "_storedData": 10
        },
        "metadata": {
          "VM": "SolidVM",
          "history": "SimpleStorage"
        }
      },
      "type": "CONTRACT"
    }
  ],
  "txParams": {
    "gasLimit": 32100000000,
    "gasPrice": 1
  }
}' \
"https://<strato_address>/strato/v2.3/transaction?resolve=true"

Enable history in BlockApps Rest by setting the history property to the contract name of the options object.

const newOptions = {
  ...options,
  VM: "SolidVM",
  history: "SimpleStorage"
}

const contract = {
  name: "SimpleStorage",
  source: contractSrc,
  args: {
    _storedData: 10
  }
}
const contractResults = await rest.createContract(stratoUser, contract, newOptions)

Note

If a contract's history has been toggled from off → on, this transaction and all subsequent transactions will be recorded in the contract's history table. History will continue to be recorded until history has been toggled off again.

Disabling Contract History

Contract history may be disabled by setting the nohistory property within the transaction payload metadata object to the name of the contract(s) for which to disable history. Since history is disabled by default, this is useful when further recording of contract history is no longer needed.

  • nohistory: string
    • The name of the contract for which to disable history.
      • SimpleStorage
    • A comma separated list of contracts for which to disable history.
      • SimpleStorage,MyContract

Example

This example would disable a contract's history

curl -X POST \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
  "txs": [
    {
      "payload": {
        "contractName": "SimpleStorage",
        "contractAddress": "<contract-address>",
        "method": "set",
        "args": {
          "_storedData": 11
        },
        "metadata": {
          "nohistory": "SimpleStorage"
        }
      },
      "type": "FUNCTION"
    }
  ],
  "txParams": {
    "gasLimit": 32100000000,
    "gasPrice": 1
  }
}' \
"https://<strato_address>/strato/v2.3/transaction?resolve=true"

Disable history in BlockApps Rest by setting the the nohistory property to the contract name in the options object.

const newOptions = {
  ...options,
  nohistory: "SimpleStorage"
}

const transaction = {
  contract : {
    name: "SimpleStorage",
    address: contractAddress,
  },
  method: "set",
  args: {
    _storedData: 11
  }
}
const results = await rest.callList(stratoUser, [transaction], newOptions)

Note

If a contract's history has been toggled from on → off, all previous history of the contract's state is still maintained, however this transaction and any future transactions will not be recorded in the history table. History will not be recorded until it is toggled on again.

Accessing Contract History

A contract's history may be accessed through the Cirrus API. Cirrus records all contracts of the same name within the same history table, just like normal contract tables. The contents of a contract's history table is its state data and relevant timestamp and transaction information. This allows you to know exactly when a change occurred what address initiated the transaction, and in what transaction the change occurred.

Contract history tables are accessible through the following API endpoint:

GET https://<strato_address>/cirrus/search/history@<contract-name>

Example

Imagine a SimpleStorage contract is created with the initial value of 10. Then another user sets storedData to 5. Then it is set to 15. By querying history@SimpleStorage, we can see each of these changes as separate records in the history table.

In the query we specify the specific instance of this contract by its address, and we sort in order of oldest to newest by block_timestamp.

curl -X GET \
-H "Authorization: Bearer <token>" \
-H "Accept: application/json" \
"https://<strato_address>/cirrus/search/history@SimpleStorage?address=eq.<contract-address>&order=block_timestamp.asc"
const query = {
  address: `eq.${contractAddress}`,
  order: 'block_timestamp.asc'
}

const newOptions = {
  ...options,
  query
}

const contract = {
  name: 'history@SimpleStorage'
}

const rows = await rest.search(stratoUser, contract, newOptions)

Response

[
  {
    "address": "803af30af892a9d84aa2231077779e143ea80fb0",
    "chainId": "",
    "block_hash": "5b336c2537afda79291581ff4f8d89138ec653c0d137192e6b2e931a0c890da1",
    "block_timestamp": "2021-09-28 15:19:17 UTC",
    "block_number": "6",
    "transaction_hash": "2f3fd0cefd452a1dbf539ff443a93b3f098a6485b33dbc83e3642b982663f1bf",
    "transaction_sender": "f6fedad2c09578a52100835c27de7927d73e6f2c",
    "transaction_function_name": "",
    "storedData": 10
  },
  {
    "address": "803af30af892a9d84aa2231077779e143ea80fb0",
    "chainId": "",
    "block_hash": "3b370b4061dc7643204123eb112f416507ad322cec015cf82f7434a6062e2ece",
    "block_timestamp": "2021-09-28 15:25:41 UTC",
    "block_number": "7",
    "transaction_hash": "1f2b255f01e0f80ed95c028a55adb29f7603916638f3b3aaf810d4e47237fc62",
    "transaction_sender": "008d73e6f2cf6fedad235c27de7927c09578a521",
    "transaction_function_name": "",
    "storedData": 5
  },
  {
    "address": "803af30af892a9d84aa2231077779e143ea80fb0",
    "chainId": "",
    "block_hash": "c7643204123eb062e2ece13b370b4061d12f416507ad322cec015cf82f7434a6",
    "block_timestamp": "2021-09-28 15:28:10 UTC",
    "block_number": "7",
    "transaction_hash": "1f2b255f01e0f80ed95c028a55adb29f7603916638f3b3aaf810d4e47237fc62",
    "transaction_sender": "f6fedad2c09578a52100835c27de7927d73e6f2c",
    "transaction_function_name": "",
    "storedData": 15
  }
]

As shown in the response, the history of events as they happened are recorded. The initial value of storedData was set to 5 by f6fedad2c09578a52100835c27de7927d73e6f2c in transaction 2f3fd0cefd452a1dbf539ff443a93b3f098a6485b33dbc83e3642b982663f1bf. Then in the next listing storedData was set to 15 a few minutes later, and so on.