github.com/true-sqn/fabric@v2.1.1+incompatible/docs/source/developapps/smartcontract.md (about)

     1  # Smart Contract Processing
     2  
     3  **Audience**: Architects, Application and smart contract developers
     4  
     5  At the heart of a blockchain network is a smart contract. In PaperNet, the code
     6  in the commercial paper smart contract defines the valid states for commercial
     7  paper, and the transaction logic that transition a paper from one state to
     8  another. In this topic, we're going to show you how to implement a real world
     9  smart contract that governs the process of issuing, buying and redeeming
    10  commercial paper.
    11  
    12  We're going to cover:
    13  
    14  * [What is a smart contract and why it's important](#smart-contract)
    15  * [How to define a smart contract](#contract-class)
    16  * [How to define a transaction](#transaction-definition)
    17  * [How to implement a transaction](#transaction-logic)
    18  * [How to represent a business object in a smart contract](#representing-an-object)
    19  * [How to store and retrieve an object in the ledger](#access-the-ledger)
    20  
    21  If you'd like, you can [download the sample](../install.html) and even [run it
    22  locally](../tutorial/commercial_paper.html). It is written in JavaScript and Java, but
    23  the logic is quite language independent, so you'll easily be able to see what's
    24  going on! (The sample will become available for Go as well.)
    25  
    26  ## Smart Contract
    27  
    28  A smart contract defines the different states of a business object and governs
    29  the processes that move the object between these different states. Smart
    30  contracts are important because they allow architects and smart contract
    31  developers to define the key business processes and data that are shared across
    32  the different organizations collaborating in a blockchain network.
    33  
    34  In the PaperNet network, the smart contract is shared by the different network
    35  participants, such as MagnetoCorp and DigiBank.  The same version of the smart
    36  contract must be used by all applications connected to the network so that they
    37  jointly implement the same shared business processes and data.
    38  
    39  ## Implementation Languages
    40  
    41  There are two runtimes that are supported, the Java Virtual Machine and Node.js. This
    42  gives the opportunity to use one of JavaScript, TypeScript, Java or any other language
    43  that can run on one of these supported runtimes.
    44  
    45  In Java and TypeScript, annotations or decorators are used to provide information about
    46  the smart contract and it's structure. This allows for a richer development experience ---
    47  for example, author information or return types can be enforced. Within JavaScript,
    48  conventions must be followed, therefore, there are limitations around what can be
    49  determined automatically.
    50  
    51  Examples here are given in both JavaScript and Java.
    52  
    53  ## Contract class
    54  
    55  A copy of the PaperNet commercial paper smart contract is contained in a single
    56  file. View it with your browser, or open it in your favorite editor if you've downloaded it.
    57    - `papercontract.js` - [JavaScript version](https://github.com/hyperledger/fabric-samples/blob/{BRANCH}/commercial-paper/organization/magnetocorp/contract/lib/papercontract.js)
    58    - `CommercialPaperContract.java` - [Java version](https://github.com/hyperledger/fabric-samples/blob/{BRANCH}/commercial-paper/organization/magnetocorp//contract-java/src/main/java/org/example/CommercialPaperContract.java)
    59  
    60  
    61  You may notice from the file path that this is MagnetoCorp's copy of the smart
    62  contract.  MagnetoCorp and DigiBank must agree on the version of the smart contract
    63  that they are going to use. For now, it doesn't matter which organization's copy
    64  you use, they are all the same.
    65  
    66  Spend a few moments looking at the overall structure of the smart contract;
    67  notice that it's quite short! Towards the top of the file, you'll see
    68  that there's a definition for the commercial paper smart contract:
    69  <details open="true">
    70  <summary>JavaScript</summary>
    71  ```JavaScript
    72  class CommercialPaperContract extends Contract {...}
    73  ```
    74  </details>
    75  
    76  <details>
    77  <summary>Java</summary>
    78  ```Java
    79  @Contract(...)
    80  @Default
    81  public class CommercialPaperContract implements ContractInterface {...}
    82  ```
    83  </details>
    84  
    85  
    86  The `CommercialPaperContract` class contains the transaction definitions for commercial paper -- **issue**, **buy**
    87  and **redeem**. It's these transactions that bring commercial papers into
    88  existence and move them through their lifecycle. We'll examine these
    89  [transactions](#transaction-definition) soon, but for now notice for JavaScript, that the
    90  `CommericalPaperContract` extends the Hyperledger Fabric `Contract`
    91  [class](https://hyperledger.github.io/fabric-chaincode-node/master/api/fabric-contract-api.Contract.html).
    92  
    93  With Java, the class must be decorated with the `@Contract(...)` annotation. This provides the opportunity
    94  to supply additional information about the contract, such as license and author. The `@Default()` annotation
    95  indicates that this contract class is the default contract class. Being able to mark a contract class as the
    96  default contract class is useful in some smart contracts which have multiple contract classes.
    97  
    98  If you are using a TypeScript implementation, there are similar `@Contract(...)` annotations that fulfill the same purpose as in Java.
    99  
   100  For more information on the available annotations, consult the available API documentation:
   101  * [API documentation for Java smart contracts](https://hyperledger.github.io/fabric-chaincode-java/)
   102  * [API documentation for Node.js smart contracts](https://hyperledger.github.io/fabric-chaincode-node/)
   103  
   104  The Fabric contract class is also available for smart contracts written in Go. While we do not discuss the Go contract API in this topic, it uses similar concepts as the API for Java and JavaScript:
   105  * [API documentation for Go smart contracts](https://github.com/hyperledger/fabric-contract-api-go)
   106  
   107  These classes, annotations, and the `Context` class, were brought into scope earlier:
   108  
   109  <details open="true">
   110  <summary>JavaScript</summary>
   111  ```JavaScript
   112  const { Contract, Context } = require('fabric-contract-api');
   113  ```
   114  </details>
   115  
   116  <details>
   117  <summary>Java</summary>
   118  ```Java
   119  import org.hyperledger.fabric.contract.Context;
   120  import org.hyperledger.fabric.contract.ContractInterface;
   121  import org.hyperledger.fabric.contract.annotation.Contact;
   122  import org.hyperledger.fabric.contract.annotation.Contract;
   123  import org.hyperledger.fabric.contract.annotation.Default;
   124  import org.hyperledger.fabric.contract.annotation.Info;
   125  import org.hyperledger.fabric.contract.annotation.License;
   126  import org.hyperledger.fabric.contract.annotation.Transaction;
   127  ```
   128  </details>
   129  
   130  
   131  Our commercial paper contract will use built-in features of these classes, such
   132  as automatic method invocation, a
   133  [per-transaction context](./transactioncontext.html),
   134  [transaction handlers](./transactionhandler.html), and class-shared state.
   135  
   136  Notice also how the JavaScript class constructor uses its
   137  [superclass](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super)
   138  to initialize itself with an explicit [contract name](./contractname.html):
   139  
   140  ```JavaScript
   141  constructor() {
   142      super('org.papernet.commercialpaper');
   143  }
   144  ```
   145  
   146  With the Java class, the constructor is blank as the explicit contract name can be specified in the `@Contract()` annotation. If it's absent, then the name of the class is used.
   147  
   148  Most importantly, `org.papernet.commercialpaper` is very descriptive -- this smart
   149  contract is the agreed definition of commercial paper for all PaperNet
   150  organizations.
   151  
   152  Usually there will only be one smart contract per file -- contracts tend to have
   153  different lifecycles, which makes it sensible to separate them. However, in some
   154  cases, multiple smart contracts might provide syntactic help for applications,
   155  e.g. `EuroBond`, `DollarBond`, `YenBond`, but essentially provide the same
   156  function. In such cases, smart contracts and transactions can be disambiguated.
   157  
   158  ## Transaction definition
   159  
   160  Within the class, locate the **issue** method.
   161  <details open="true">
   162  <summary>JavaScript</summary>
   163  ```JavaScript
   164  async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) {...}
   165  ```
   166  </details>
   167  
   168  <details>
   169  <summary>Java</summary>
   170  ```Java
   171  @Transaction
   172  public CommercialPaper issue(CommercialPaperContext ctx,
   173                               String issuer,
   174                               String paperNumber,
   175                               String issueDateTime,
   176                               String maturityDateTime,
   177                               int faceValue) {...}
   178  ```
   179  </details>
   180  
   181  The Java annotation `@Transaction` is used to mark this method as a transaction definition; TypeScript has an equivalent annotation.
   182  
   183  This function is given control whenever this contract is called to `issue` a
   184  commercial paper. Recall how commercial paper 00001 was created with the
   185  following transaction:
   186  
   187  ```
   188  Txn = issue
   189  Issuer = MagnetoCorp
   190  Paper = 00001
   191  Issue time = 31 May 2020 09:00:00 EST
   192  Maturity date = 30 November 2020
   193  Face value = 5M USD
   194  ```
   195  
   196  We've changed the variable names for programming style, but see how these
   197  properties map almost directly to the `issue` method variables.
   198  
   199  The `issue` method is automatically given control by the contract whenever an
   200  application makes a request to issue a commercial paper. The transaction
   201  property values are made available to the method via the corresponding
   202  variables. See how an application submits a transaction using the Hyperledger
   203  Fabric SDK in the [application](./application.html) topic, using a sample
   204  application program.
   205  
   206  You might have noticed an extra variable in the **issue** definition -- `ctx`.
   207  It's called the [**transaction context**](./transactioncontext.html), and it's
   208  always first. By default, it maintains both per-contract and per-transaction
   209  information relevant to [transaction logic](#transaction-logic). For example, it
   210  would contain MagnetoCorp's specified transaction identifier, a MagnetoCorp
   211  issuing user's digital certificate, as well as access to the ledger API.
   212  
   213  See how the smart contract extends the default transaction context by
   214  implementing its own `createContext()` method rather than accepting the
   215  default implementation:
   216  
   217  <details open="true">
   218  <summary>JavaScript</summary>
   219  ```JavaScript
   220  createContext() {
   221    return new CommercialPaperContext()
   222  }
   223  ```
   224  </details>
   225  
   226  <details>
   227  <summary>Java</summary>
   228  ```Java
   229  @Override
   230  public Context createContext(ChaincodeStub stub) {
   231       return new CommercialPaperContext(stub);
   232  }
   233  ```
   234  </details>
   235  
   236  
   237  This extended context adds a custom property `paperList` to the defaults:
   238  <details open="true">
   239  <summary>JavaScript</summary>
   240  ```JavaScript
   241  class CommercialPaperContext extends Context {
   242  
   243    constructor() {
   244      super();
   245      // All papers are held in a list of papers
   246      this.paperList = new PaperList(this);
   247  }
   248  ```
   249  </details>
   250  
   251  <details>
   252  <summary>Java</summary>
   253  ```Java
   254  class CommercialPaperContext extends Context {
   255      public CommercialPaperContext(ChaincodeStub stub) {
   256          super(stub);
   257          this.paperList = new PaperList(this);
   258      }
   259      public PaperList paperList;
   260  }
   261  ```
   262  </details>
   263  
   264  We'll soon see how `ctx.paperList` can be subsequently used to help store and
   265  retrieve all PaperNet commercial papers.
   266  
   267  To solidify your understanding of the structure of a smart contract transaction,
   268  locate the **buy** and **redeem** transaction definitions, and see if you can
   269  see how they map to their corresponding commercial paper transactions.
   270  
   271  The **buy** transaction:
   272  
   273  ```
   274  Txn = buy
   275  Issuer = MagnetoCorp
   276  Paper = 00001
   277  Current owner = MagnetoCorp
   278  New owner = DigiBank
   279  Purchase time = 31 May 2020 10:00:00 EST
   280  Price = 4.94M USD
   281  ```
   282  
   283  <details open="true">
   284  <summary>JavaScript</summary>
   285  ```JavaScript
   286  async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseTime) {...}
   287  ```
   288  </details>
   289  
   290  <details>
   291  <summary>Java</summary>
   292  ```Java
   293  @Transaction
   294  public CommercialPaper buy(CommercialPaperContext ctx,
   295                             String issuer,
   296                             String paperNumber,
   297                             String currentOwner,
   298                             String newOwner,
   299                             int price,
   300                             String purchaseDateTime) {...}
   301  ```
   302  </details>
   303  
   304  The **redeem** transaction:
   305  
   306  ```
   307  Txn = redeem
   308  Issuer = MagnetoCorp
   309  Paper = 00001
   310  Redeemer = DigiBank
   311  Redeem time = 31 Dec 2020 12:00:00 EST
   312  ```
   313  
   314  <details open="true">
   315  <summary>JavaScript</summary>
   316  ```JavaScript
   317  async redeem(ctx, issuer, paperNumber, redeemingOwner, redeemDateTime) {...}
   318  ```
   319  </details>
   320  
   321  <details>
   322  <summary>Java</summary>
   323  ```Java
   324  @Transaction
   325  public CommercialPaper redeem(CommercialPaperContext ctx,
   326                                String issuer,
   327                                String paperNumber,
   328                                String redeemingOwner,
   329                                String redeemDateTime) {...}
   330  ```
   331  </details>
   332  
   333  In both cases, observe the 1:1 correspondence between the commercial paper
   334  transaction and the smart contract method definition.
   335  
   336  All of the JavaScript functions use the `async` and `await`
   337  [keywords](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) which allow JavaScript functions to be treated as if they were synchronous function calls.
   338  
   339  
   340  ## Transaction logic
   341  
   342  Now that you've seen how contracts are structured and transactions are defined,
   343  let's focus on the logic within the smart contract.
   344  
   345  Recall the first **issue** transaction:
   346  
   347  ```
   348  Txn = issue
   349  Issuer = MagnetoCorp
   350  Paper = 00001
   351  Issue time = 31 May 2020 09:00:00 EST
   352  Maturity date = 30 November 2020
   353  Face value = 5M USD
   354  ```
   355  
   356  It results in the **issue** method being passed control:
   357  <details open="true">
   358  <summary>JavaScript</summary>
   359  ```JavaScript
   360  async issue(ctx, issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) {
   361  
   362     // create an instance of the paper
   363    let paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue);
   364  
   365    // Smart contract, rather than paper, moves paper into ISSUED state
   366    paper.setIssued();
   367  
   368    // Newly issued paper is owned by the issuer
   369    paper.setOwner(issuer);
   370  
   371    // Add the paper to the list of all similar commercial papers in the ledger world state
   372    await ctx.paperList.addPaper(paper);
   373  
   374    // Must return a serialized paper to caller of smart contract
   375    return paper.toBuffer();
   376  }
   377  ```
   378  </details>
   379  
   380  <details>
   381  <summary>Java</summary>
   382  ```Java
   383  @Transaction
   384  public CommercialPaper issue(CommercialPaperContext ctx,
   385                                String issuer,
   386                                String paperNumber,
   387                                String issueDateTime,
   388                                String maturityDateTime,
   389                                int faceValue) {
   390  
   391      System.out.println(ctx);
   392  
   393      // create an instance of the paper
   394      CommercialPaper paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime,
   395              faceValue,issuer,"");
   396  
   397      // Smart contract, rather than paper, moves paper into ISSUED state
   398      paper.setIssued();
   399  
   400      // Newly issued paper is owned by the issuer
   401      paper.setOwner(issuer);
   402  
   403      System.out.println(paper);
   404      // Add the paper to the list of all similar commercial papers in the ledger
   405      // world state
   406      ctx.paperList.addPaper(paper);
   407  
   408      // Must return a serialized paper to caller of smart contract
   409      return paper;
   410  }
   411  ```
   412  </details>
   413  
   414  
   415  The logic is simple: take the transaction input variables, create a new
   416  commercial paper `paper`, add it to the list of all commercial papers using
   417  `paperList`, and return the new commercial paper (serialized as a buffer) as the
   418  transaction response.
   419  
   420  See how `paperList` is retrieved from the transaction context to provide access
   421  to the list of commercial papers. `issue()`, `buy()` and `redeem()` continually
   422  re-access `ctx.paperList` to keep the list of commercial papers up-to-date.
   423  
   424  The logic for the **buy** transaction is a little more elaborate:
   425  <details open="true">
   426  <summary>JavaScript</summary>
   427  ```JavaScript
   428  async buy(ctx, issuer, paperNumber, currentOwner, newOwner, price, purchaseDateTime) {
   429  
   430    // Retrieve the current paper using key fields provided
   431    let paperKey = CommercialPaper.makeKey([issuer, paperNumber]);
   432    let paper = await ctx.paperList.getPaper(paperKey);
   433  
   434    // Validate current owner
   435    if (paper.getOwner() !== currentOwner) {
   436        throw new Error('Paper ' + issuer + paperNumber + ' is not owned by ' + currentOwner);
   437    }
   438  
   439    // First buy moves state from ISSUED to TRADING
   440    if (paper.isIssued()) {
   441        paper.setTrading();
   442    }
   443  
   444    // Check paper is not already REDEEMED
   445    if (paper.isTrading()) {
   446        paper.setOwner(newOwner);
   447    } else {
   448        throw new Error('Paper ' + issuer + paperNumber + ' is not trading. Current state = ' +paper.getCurrentState());
   449    }
   450  
   451    // Update the paper
   452    await ctx.paperList.updatePaper(paper);
   453    return paper.toBuffer();
   454  }
   455  ```
   456  </details>
   457  
   458  <details>
   459  <summary>Java</summary>
   460  ```Java
   461  @Transaction
   462  public CommercialPaper buy(CommercialPaperContext ctx,
   463                             String issuer,
   464                             String paperNumber,
   465                             String currentOwner,
   466                             String newOwner,
   467                             int price,
   468                             String purchaseDateTime) {
   469  
   470      // Retrieve the current paper using key fields provided
   471      String paperKey = State.makeKey(new String[] { paperNumber });
   472      CommercialPaper paper = ctx.paperList.getPaper(paperKey);
   473  
   474      // Validate current owner
   475      if (!paper.getOwner().equals(currentOwner)) {
   476          throw new RuntimeException("Paper " + issuer + paperNumber + " is not owned by " + currentOwner);
   477      }
   478  
   479      // First buy moves state from ISSUED to TRADING
   480      if (paper.isIssued()) {
   481          paper.setTrading();
   482      }
   483  
   484      // Check paper is not already REDEEMED
   485      if (paper.isTrading()) {
   486          paper.setOwner(newOwner);
   487      } else {
   488          throw new RuntimeException(
   489                  "Paper " + issuer + paperNumber + " is not trading. Current state = " + paper.getState());
   490      }
   491  
   492      // Update the paper
   493      ctx.paperList.updatePaper(paper);
   494      return paper;
   495  }
   496  ```
   497  </details>
   498  
   499  See how the transaction checks `currentOwner` and that `paper` is `TRADING`
   500  before changing the owner with `paper.setOwner(newOwner)`. The basic flow is
   501  simple though -- check some pre-conditions, set the new owner, update the
   502  commercial paper on the ledger, and return the updated commercial paper
   503  (serialized as a buffer) as the transaction response.
   504  
   505  Why don't you see if you can understand the logic for the **redeem**
   506  transaction?
   507  
   508  ## Representing an object
   509  
   510  We've seen how to define and implement the **issue**, **buy** and **redeem**
   511  transactions using the `CommercialPaper` and `PaperList` classes. Let's end
   512  this topic by seeing how these classes work.
   513  
   514  Locate the `CommercialPaper` class:
   515  
   516  <details open="true">
   517  <summary>JavaScript</summary>
   518  In the
   519  [paper.js file](https://github.com/hyperledger/fabric-samples/blob/{BRANCH}/commercial-paper/organization/magnetocorp/contract/lib/paper.js):
   520  
   521  ```JavaScript
   522  class CommercialPaper extends State {...}
   523  ```
   524  </details>
   525  
   526  <details>
   527  <summary>Java</summary>
   528  In the [CommercialPaper.java file](https://github.com/hyperledger/fabric-samples/blob/release-1.4/commercial-paper/organization/magnetocorp/contract-java/src/main/java/org/example/CommercialPaper.java):
   529  
   530  
   531  ```Java
   532  @DataType()
   533  public class CommercialPaper extends State {...}
   534  ```
   535  </details>
   536  
   537  
   538  This class contains the in-memory representation of a commercial paper state.
   539  See how the `createInstance` method initializes a new commercial paper with the
   540  provided parameters:
   541  
   542  <details open="true">
   543  <summary>JavaScript</summary>
   544  ```JavaScript
   545  static createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue) {
   546    return new CommercialPaper({ issuer, paperNumber, issueDateTime, maturityDateTime, faceValue });
   547  }
   548  ```
   549  </details>
   550  
   551  <details>
   552  <summary>Java</summary>
   553  ```Java
   554  public static CommercialPaper createInstance(String issuer, String paperNumber, String issueDateTime,
   555          String maturityDateTime, int faceValue, String owner, String state) {
   556      return new CommercialPaper().setIssuer(issuer).setPaperNumber(paperNumber).setMaturityDateTime(maturityDateTime)
   557              .setFaceValue(faceValue).setKey().setIssueDateTime(issueDateTime).setOwner(owner).setState(state);
   558  }
   559  ```
   560  </details>
   561  
   562  Recall how this class was used by the **issue** transaction:
   563  
   564  <details open="true">
   565  <summary>JavaScript</summary>
   566  ```JavaScript
   567  let paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime, faceValue);
   568  ```
   569  </details>
   570  
   571  <details>
   572  <summary>Java</summary>
   573  ```Java
   574  CommercialPaper paper = CommercialPaper.createInstance(issuer, paperNumber, issueDateTime, maturityDateTime,
   575          faceValue,issuer,"");
   576  ```
   577  </details>
   578  
   579  See how every time the issue transaction is called, a new in-memory instance of
   580  a commercial paper is created containing the transaction data.
   581  
   582  A few important points to note:
   583  
   584    * This is an in-memory representation; we'll see
   585      [later](#accessing-the-ledger) how it appears on the ledger.
   586  
   587  
   588    * The `CommercialPaper` class extends the `State` class. `State` is an
   589      application-defined class which creates a common abstraction for a state.
   590      All states have a business object class which they represent, a composite
   591      key, can be serialized and de-serialized, and so on.  `State` helps our code
   592      be more legible when we are storing more than one business object type on
   593      the ledger. Examine the `State` class in the `state.js`
   594      [file](https://github.com/hyperledger/fabric-samples/blob/{BRANCH}/commercial-paper/organization/magnetocorp/contract/ledger-api/state.js).
   595  
   596  
   597    * A paper computes its own key when it is created -- this key will be used
   598      when the ledger is accessed. The key is formed from a combination of
   599      `issuer` and `paperNumber`.
   600  
   601      ```JavaScript
   602      constructor(obj) {
   603        super(CommercialPaper.getClass(), [obj.issuer, obj.paperNumber]);
   604        Object.assign(this, obj);
   605      }
   606      ```
   607  
   608  
   609    * A paper is moved to the `ISSUED` state by the transaction, not by the paper
   610      class. That's because it's the smart contract that governs the lifecycle
   611      state of the paper. For example, an `import` transaction might create a new
   612      set of papers immediately in the `TRADING` state.
   613  
   614  The rest of the `CommercialPaper` class contains simple helper methods:
   615  
   616  ```JavaScript
   617  getOwner() {
   618      return this.owner;
   619  }
   620  ```
   621  
   622  Recall how methods like this were used by the smart contract to move the
   623  commercial paper through its lifecycle. For example, in the **redeem**
   624  transaction we saw:
   625  
   626  ```JavaScript
   627  if (paper.getOwner() === redeemingOwner) {
   628    paper.setOwner(paper.getIssuer());
   629    paper.setRedeemed();
   630  }
   631  ```
   632  
   633  ## Access the ledger
   634  
   635  Now locate the `PaperList` class in the `paperlist.js`
   636  [file](https://github.com/hyperledger/fabric-samples/blob/{BRANCH}/commercial-paper/organization/magnetocorp/contract/lib/paperlist.js):
   637  
   638  ```JavaScript
   639  class PaperList extends StateList {
   640  ```
   641  
   642  This utility class is used to manage all PaperNet commercial papers in
   643  Hyperledger Fabric state database. The PaperList data structures are described
   644  in more detail in the [architecture topic](./architecture.html).
   645  
   646  Like the `CommercialPaper` class, this class extends an application-defined
   647  `StateList` class which creates a common abstraction for a list of states -- in
   648  this case, all the commercial papers in PaperNet.
   649  
   650  The `addPaper()` method is a simple veneer over the `StateList.addState()`
   651  method:
   652  
   653  ```JavaScript
   654  async addPaper(paper) {
   655    return this.addState(paper);
   656  }
   657  ```
   658  
   659  You can see in the `StateList.js`
   660  [file](https://github.com/hyperledger/fabric-samples/blob/{BRANCH}/commercial-paper/organization/magnetocorp/contract/ledger-api/statelist.js)
   661  how the `StateList` class uses the Fabric API `putState()` to write the
   662  commercial paper as state data in the ledger:
   663  
   664  ```JavaScript
   665  async addState(state) {
   666    let key = this.ctx.stub.createCompositeKey(this.name, state.getSplitKey());
   667    let data = State.serialize(state);
   668    await this.ctx.stub.putState(key, data);
   669  }
   670  ```
   671  
   672  Every piece of state data in a ledger requires these two fundamental elements:
   673  
   674    * **Key**: `key` is formed with `createCompositeKey()` using a fixed name and
   675      the key of `state`. The name was assigned when the `PaperList` object was
   676      constructed, and `state.getSplitKey()` determines each state's unique key.
   677  
   678  
   679    * **Data**: `data` is simply the serialized form of the commercial paper
   680      state, created using the `State.serialize()` utility method. The `State`
   681      class serializes and deserializes data using JSON, and the State's business
   682      object class as required, in our case `CommercialPaper`, again set when the
   683      `PaperList` object was constructed.
   684  
   685  
   686  Notice how a `StateList` doesn't store anything about an individual state or the
   687  total list of states -- it delegates all of that to the Fabric state database.
   688  This is an important design pattern -- it reduces the opportunity for [ledger
   689  MVCC collisions](../readwrite.html) in Hyperledger Fabric.
   690  
   691  The StateList `getState()` and `updateState()` methods work in similar ways:
   692  
   693  ```JavaScript
   694  async getState(key) {
   695    let ledgerKey = this.ctx.stub.createCompositeKey(this.name, State.splitKey(key));
   696    let data = await this.ctx.stub.getState(ledgerKey);
   697    let state = State.deserialize(data, this.supportedClasses);
   698    return state;
   699  }
   700  ```
   701  
   702  ```JavaScript
   703  async updateState(state) {
   704    let key = this.ctx.stub.createCompositeKey(this.name, state.getSplitKey());
   705    let data = State.serialize(state);
   706    await this.ctx.stub.putState(key, data);
   707  }
   708  ```
   709  
   710  See how they use the Fabric APIs `putState()`, `getState()` and
   711  `createCompositeKey()` to access the ledger. We'll expand this smart contract
   712  later to list all commercial papers in paperNet -- what might the method look
   713  like to implement this ledger retrieval?
   714  
   715  That's it! In this topic you've understood how to implement the smart contract
   716  for PaperNet.  You can move to the next sub topic to see how an application
   717  calls the smart contract using the Fabric SDK.
   718  
   719  <!--- Licensed under Creative Commons Attribution 4.0 International License
   720  https://creativecommons.org/licenses/by/4.0/ -->