github.com/Hnampk/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/ -->