Writing smart contract using Hyperledger Fabric

Comprehensive study notes, diagrams, and exam preparation for Writing smart contract using Hyperledger Fabric.

Writing Smart Contract using Hyperledger Fabric

Definition

A smart contract in Hyperledger Fabric is a piece of application logic, deployed as chaincode, that runs on Fabric peers and defines the rules for reading and updating the ledger state in a permissioned blockchain network.

In simple terms, a smart contract in Fabric:

  • Receives transaction requests from client applications
  • Verifies conditions defined by business rules
  • Reads and writes data to the ledger state
  • Produces results that are endorsed and then ordered into blocks

For example, if a company wants to ensure that an asset can only be transferred by its current owner, the smart contract enforces that rule automatically. If the rule is violated, the transaction is rejected. This makes Fabric smart contracts essential for trustworthy multi-party business automation.


Main Content

1. Chaincode and Business Logic Design

Chaincode is the core implementation of a smart contract in Fabric

In Hyperledger Fabric, smart contracts are usually written as chaincode. Chaincode contains the functions that define how ledger data should be created, queried, updated, and validated. It is the code that runs on endorsing peers and represents the business logic of the blockchain application. For example, in a supply chain system, chaincode may include functions such as createAsset, transferAsset, updateLocation, and getAssetHistory.

Business logic must be modeled around real-world rules

A strong smart contract begins with clearly understanding the business process. The contract should reflect practical constraints, such as who is allowed to invoke a function, what conditions must be met before an update is accepted, and how data integrity should be maintained. For instance, in a healthcare network, only authorized hospitals may update patient referral records, while insurance partners may only read limited fields. The chaincode should enforce these permissions and rules directly.

A good design also includes:

  • Clear asset structure
  • Unique identifiers for records
  • Validation rules for input data
  • Error handling for invalid requests
  • Separation of read-only query logic from state-changing transactions

Example:

  async createAsset(ctx, assetId, owner, value) {
      const assetExists = await this.assetExists(ctx, assetId);
      if (assetExists) {
          throw new Error(`Asset ${assetId} already exists`);
      }
      const asset = {
          assetId,
          owner,
          value,
      };
      await ctx.stub.putState(assetId, Buffer.from(JSON.stringify(asset)));
  }

This example shows a basic smart contract rule: no duplicate asset IDs are allowed.

2. Fabric Programming Model and Contract Structure

Hyperledger Fabric provides a structured programming model

Fabric smart contracts are usually built using the Fabric Contract API, which simplifies chaincode development. The contract class contains methods that map to transaction functions. A transaction function is executed when a client submits a proposal through the Fabric SDK or REST layer. The contract can define initLedger, createAsset, readAsset, updateAsset, deleteAsset, and more.

The common structure includes:

  • Contract class definition
  • @Transaction methods or standard public functions depending on language
  • Helper methods for validation and queries
  • Ledger interaction using Fabric APIs such as putState, getState, deleteState, and getQueryResult

The contract must interact properly with the stub and context

The transaction context (ctx) provides access to the chaincode stub (ctx.stub) and client identity information. Through the stub, the contract can read/write world state, access transaction IDs, query history, and inspect metadata. Using the client identity, the contract can enforce role-based access control.

Example of access control:

  const clientIdentity = ctx.clientIdentity.getMSPID();
  if (clientIdentity !== 'Org1MSP') {
      throw new Error('Only Org1 can perform this action');
  }

This matters in enterprise settings because different organizations in the network may have different permissions. The chaincode can therefore ensure that only approved participants can execute sensitive operations.

A well-structured contract should also:

  • Keep transaction functions small and focused
  • Avoid unnecessary complex calculations
  • Use helper functions for reusable checks
  • Return meaningful error messages
  • Preserve deterministic behavior across peers

3. Transaction Flow, Validation, and Ledger Interaction

Smart contract execution follows the Fabric transaction lifecycle

When a client application submits a request, Fabric does not immediately commit it to the ledger. Instead, the proposal is first sent to endorsing peers, where chaincode simulates execution and produces a read-write set. The endorsement policy specifies which peers must approve the result. After endorsement, the transaction goes to ordering service, which sequences transactions into blocks, and then peers validate and commit the block.

This means the smart contract must be written with deterministic behavior so that all endorsing peers produce the same result. It should avoid:

  • Random number generation
  • Current timestamp dependence for logic decisions unless handled carefully
  • External network calls
  • Non-deterministic iteration over unordered data

Ledger interaction happens through state reads and writes

Hyperledger Fabric uses a world state database for current values and a blockchain ledger for immutable history. Smart contracts usually work with the world state for fast access while the full ledger records every transaction. Functions like getState() fetch the latest value of a key, while putState() updates the current value.

Example:

  assetBytes, err := ctx.GetStub().GetState(assetID)
  if err != nil {
      return err
  }
  if assetBytes == nil {
      return fmt.Errorf("asset %s does not exist", assetID)
  }

In addition, smart contracts often validate:

  • Whether a record already exists before creation
  • Whether a record exists before update or delete
  • Whether input fields meet expected formats
  • Whether the invoker has permission to act

For more advanced applications, chaincode can also:

  • Perform rich queries with CouchDB
  • Retrieve historical states for auditing
  • Emit events for external systems
  • Support composite keys for efficient indexing

Working / Process

1. Design the business case and data model

Start by identifying the exact business process the blockchain will automate. Define the assets, participants, relationships, and rules. Decide what data should be stored on-chain, what roles different organizations have, and what conditions must be enforced by the contract. For example, in a land registry application, the asset may be a property record with fields such as property ID, owner, location, and status.

2. Write, test, and deploy the chaincode

Implement the smart contract using a supported language such as Go, JavaScript/TypeScript, or Java. Create transaction functions for create, read, update, delete, and query operations. Use the Fabric test network or a local development environment to test chaincode behavior, validate endorsement logic, and confirm that only valid transactions are committed. Then package and install the chaincode on peers, approve it by organizations, and commit it to a channel.

3. Invoke transactions and monitor ledger updates

Once deployed, client applications use the Fabric SDK or APIs to invoke smart contract functions. The peers simulate the transaction, endorsement is collected, and the transaction is committed to the ledger. After commitment, the world state is updated and applications can query the new data. Monitoring tools can then be used to inspect logs, verify transaction IDs, and audit the chaincode’s effects.


Advantages / Applications

Secure multi-organization automation

Hyperledger Fabric smart contracts are ideal for workflows involving multiple organizations that do not fully trust one another. The contract ensures that every participant follows agreed rules, reducing disputes and manual verification.

Fine-grained access control and privacy

Fabric supports private channels, private data collections, and identity-based permissions. This makes smart contracts useful for industries where not all data should be visible to every participant, such as healthcare, finance, and trade.

Wide range of enterprise use cases

Smart contracts in Fabric can be applied to supply chain tracking, asset tokenization, insurance claims, digital identity, trade finance, certificate verification, and provenance tracking. For example, a logistics company can use chaincode to record shipment handoffs at each stage and instantly verify authenticity.


Summary

  • Hyperledger Fabric smart contracts are implemented as chaincode that defines business rules on a permissioned blockchain.
  • Writing smart contracts in Fabric requires careful design of transaction functions, validation logic, and ledger interactions.
  • The transaction flow includes proposal simulation, endorsement, ordering, validation, and commitment.
  • Fabric smart contracts are widely used for secure, scalable, and privacy-preserving enterprise applications.
  • Important terms to remember:
  • Chaincode
  • World state
  • Endorsement policy
  • Ledger
  • Transaction context
  • CouchDB
  • Private data collection