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