├── LICENSE ├── README.md ├── TradeManager.sol ├── TradeManager1.png └── TradeManager2.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Validity Labs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blockchain Showcase for Trade Finance and Supply Chain Automation 2 | 3 | This is a minimal showcase example that shows the power of blockchain for trade finance and supply chain automation. An Ethereum smart contract (SC) acts as the central interface between the involved parties. The SC reecives payments and deposits and releases them to the corresponding parties in due time. In order to facilitate easy testing with simple wallets, the entire interfacing happens via the fallback function and not via specific function calls - this is a concept that we call [SWIS contracts](https://medium.com/@validitylabs/swis-contracts-a-simpler-demonstrator-for-blackchains-and-smart-contracts-a11f2903687). 4 | 5 | ## Digital Handshake to Forward Goods and State 6 | All involved parties that are involved in the transportation chain perform a digital handshake with the smart contract to signal the handover of the goods to the next party. These handshakes are performed by means of transactions to the smart contract. When both parties have completed the handshake, the SC assumes to goods to be in control of the second party. When required, payments are being released. 7 | 8 | Initialization of the TradeManager: 9 | ![Initialization of the TradeManager](https://raw.githubusercontent.com/validitylabs/TradeManager/master/TradeManager1.png) 10 | 11 | Release of payment and deposits upon completion of the last handshake: 12 | ![Release of payments by the TradeManager](https://raw.githubusercontent.com/validitylabs/TradeManager/master/TradeManager2.png) 13 | 14 | ## Involved Parties 15 | All involved parties are identified by Ethereum addresses. As such they could be either private key controlled accounts (individuals) as well as SCs such as multi signature accounts (organizations). 16 | 17 | ### Buyer 18 | The Account that performs the initial payment of the purchase amount and the costs of both carriers. This account also has to pay a deposit at the value of the purchase amount that will be released upon completion of the purchase at the end of the transportation chain. 19 | 20 | ### Seller 21 | The seller accounts starts shipping the goods and before releasing the goods has to pay in a deposit at the value of the goods. This deposit will also be released upon completion of the purchase at the end of the transportation chain. 22 | 23 | ### Carrier 1 and 2 24 | These are carriers which transport the goods. They receive the goods and ship them from seller to buyer. They are involved in the handshakes of handing over the goods and receive their payment as soon as the handshake involving their part of the transportation chain is completed. 25 | -------------------------------------------------------------------------------- /TradeManager.sol: -------------------------------------------------------------------------------- 1 | /* 2 | This is a simple showcase smart contract example for trade finance / supply chain interactions. 3 | It could be improved in several ways: 4 | - add timeouts for state reversal (e.g. object is released by one party but not accepted by next) 5 | = add escrow payments also for carriers, otherwise they can block forever 6 | - add delivery dates for carriers, if not met their escrow balance will be punished 7 | - add insurance interface for, e.g. transport delay or damage insurance 8 | */ 9 | 10 | contract TradeHandler { 11 | address public seller; 12 | address public carrier1; 13 | address public carrier2; 14 | address public buyer; 15 | uint public purchasePrice; 16 | uint public carrier1Fee; 17 | uint public carrier2Fee; 18 | 19 | enum WaitingFor { 20 | BuyerEscrowPayment, 21 | SellerEscrowPayment, 22 | SellerRelease, 23 | Carrier1Accept, 24 | Carrier1Release, 25 | Carrier2Accept, 26 | Carrier2Release, 27 | BuyerAccept, 28 | Completed 29 | } 30 | 31 | WaitingFor state; 32 | 33 | // constructor sets all actors and fees 34 | function TradeHandler( 35 | address _seller, 36 | address _carrier1, 37 | address _carrier2, 38 | uint _carrier1Fee, 39 | uint _carrier2Fee, 40 | uint _purchasePrice) 41 | { 42 | buyer = msg.sender; 43 | seller = _seller; 44 | carrier1 = _carrier1; 45 | carrier2 = _carrier2; 46 | carrier1Fee = _carrier1Fee; 47 | carrier2Fee = _carrier2Fee; 48 | purchasePrice = _purchasePrice; 49 | } 50 | 51 | function reset( 52 | address _seller, 53 | address _carrier1, 54 | address _carrier2, 55 | uint _carrier1Fee, 56 | uint _carrier2Fee, 57 | uint _purchasePrice) 58 | { 59 | // only allow recylcing of contract if previous trade is completed 60 | if (state != WaitingFor.Completed) 61 | throw; 62 | buyer = msg.sender; 63 | seller = _seller; 64 | carrier1 = _carrier1; 65 | carrier2 = _carrier2; 66 | carrier1Fee = _carrier1Fee; 67 | carrier2Fee = _carrier2Fee; 68 | purchasePrice = _purchasePrice; 69 | } 70 | 71 | function () payable { 72 | 73 | // todo: one could check for timeouts and revert transitions if required 74 | 75 | // once trade is completed, do not allow further interaction 76 | if (state == WaitingFor.Completed) 77 | throw; 78 | 79 | // each actor is only responsible for their respective state transfer, reject all others 80 | if (msg.sender == buyer && state != WaitingFor.BuyerEscrowPayment && state != WaitingFor.BuyerAccept) 81 | throw; 82 | if (msg.sender == seller && state != WaitingFor.SellerEscrowPayment && state != WaitingFor.SellerRelease) 83 | throw; 84 | if (msg.sender == carrier1 && state != WaitingFor.Carrier1Accept && state != WaitingFor.Carrier1Release) 85 | throw; 86 | if (msg.sender == carrier2 && state != WaitingFor.Carrier2Accept && state != WaitingFor.Carrier2Release) 87 | throw; 88 | 89 | // make sure that the right amounts are being paid into this escrow contract by buyer and seller 90 | if (state == WaitingFor.BuyerEscrowPayment && msg.value != 2 * purchasePrice + carrier1Fee + carrier2Fee) 91 | throw; 92 | if (state == WaitingFor.SellerEscrowPayment && msg.value != purchasePrice) 93 | throw; 94 | 95 | // perform state transitions 96 | if (state == WaitingFor.BuyerEscrowPayment) 97 | state = WaitingFor.SellerEscrowPayment; 98 | else if (state == WaitingFor.SellerEscrowPayment) 99 | state = WaitingFor.SellerRelease; 100 | else if (state == WaitingFor.SellerRelease) 101 | state = WaitingFor.Carrier1Accept; 102 | else if (state == WaitingFor.Carrier1Accept) 103 | state = WaitingFor.Carrier1Release; 104 | else if (state == WaitingFor.Carrier1Release) 105 | state = WaitingFor.Carrier2Accept; 106 | else if (state == WaitingFor.Carrier2Accept) { 107 | state = WaitingFor.Carrier2Release; 108 | carrier1.send(carrier1Fee); 109 | } else if (state == WaitingFor.Carrier2Release) 110 | state = WaitingFor.BuyerAccept; 111 | else if (state == WaitingFor.BuyerAccept) { 112 | state = WaitingFor.Completed; 113 | carrier2.send(carrier2Fee); 114 | seller.send(2 * purchasePrice); 115 | buyer.send(purchasePrice); 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /TradeManager1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/validitylabs/TradeManager/63b86eb07d0c7ba256f012dc0f122d2643e2566e/TradeManager1.png -------------------------------------------------------------------------------- /TradeManager2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/validitylabs/TradeManager/63b86eb07d0c7ba256f012dc0f122d2643e2566e/TradeManager2.png --------------------------------------------------------------------------------