Creating an LC smart contract

The LC smart contract will serve as an interface for the LC Master contract so that we can create and deploy a new contract. The smart contract will consist of the following components:

  • Data structure
    • LCNew: To capture and store the LC details
  • Functions
    • viewLCDetails: To view the LC details
    • settleLC: To invoke a settlement request to the LC
  • Modifiers 
    • onlyAuth: Only permits buyer, seller, and the bank to access to the method
    • onlySeller: Only permits the seller to access the method
  • Event
    • SettleLCSuccessful: Triggered after a successful settlement request

Now, let's start creating the LC smart contract by following these steps:

  1. Start by creating a file called LC.sol.
  2. We will first declare the compiler version and import our dependent contracts, as shown in the following code block:
pragma solidity ^0.5.2;

import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "./LCMaster.sol";

Our compiler version is 0.5.2. We import the ERC20.sol contract from OpenZeppelin's suite. This interface will allow us to transfer tokens during settlement. We also import the LCMaster contract as we need to access the ModifyLC method in LCMaster during settlements.

  1. Next, we will define the contract and the LC structure, as shown in the following code block:
contract LC {

struct LoC {
uint LCNo;
address BuyerAcc;
address SellerAcc;
uint Amount;
uint IniAmount;
bytes2 Status;
uint DOIssue;
uint DOExpiry;
bytes32 DocHash;
}

LoC LCnew;

The LoC struct in the preceding code is used to define the parameter of the LC contract. It captures and stores the following details:

  • LC number (LCNo)
  • Buyer's Ethereum account address (BuyerAcc)
  • Seller's Ethereum account address (SellerAcc)
  • Amount available in escrow (Amount)
  • Initial amount stored to escrow (IniAmount)
  • Current status of the LC (I—Issued, P—Partially Settled, S—Settled)
  • DOI of the LC (DOIssue)
  • DOE of the LC (DOExpiry)
  • Hash of the document submitted by the Seller during settlement (DocHash)

The DocHash element is important. It is required to capture the hash of the supporting documents for settlement. Since the hash is unique and the blockchain is immutable, this makes the record tamperproof. In the case of suspicion of fraud, the hash of the documents can be easily calculated again and verified with the record stored in the blockchain for verification.

  1. Next, we define instances for the ERC20 contract and the LC Master contract, and also define a parameter to hold the bank's address for modifiers and access controls, as follows:
LCMaster LCM;
ERC20 public ERC20Interface;
address bank;
  1. In the following code, we will define our constructor:
constructor (uint LCNum,address BAcc,address SAcc,uint Amt,uint DOI,uint DOE,address bankadd) public
{
bank = bankadd;
LCnew.LCNo = LCNum;
LCnew.BuyerAcc = BAcc;
LCnew.SellerAcc = SAcc;
LCnew.Amount = Amt;
LCnew.IniAmount = Amt;
LCnew.Status = 'I' ; // I - Issued, S - Settled, P - Partially Settled
LCnew.DOIssue = DOI;
LCnew.DOExpiry = DOE;
LCnew.DocHash = 0x0;

From the preceding code, we can make the following observations:

  • The constructor takes in the input parameters sent to it by the LCMaster contract and maps it to the LC struct LCNew object.
  • These parameters now define our new contract. It also sets the default status as 'I' (Issued), the date of issue to now (current blockchain and system time), and DocHash to 0x0 (Default Hash value—No Document submitted yet).
  • It also sets the bank Ethereum address as the address that initially calls the createLC method in the LC Master contract (bankadd). This parameter is sent as part of the input parameters from the LC Master.
  • Initial amount and amount are set to the same value initially. This value (Amt) is the escrow amount.
  1. We also need to define our imported contract dependencies. The LCMaster instance is sent to the msg.sender address because the new contract is deployed by the LC Master. This is held by the LCM object. The ERC20Interface instance is set to the USD token contract address that we stored earlier. Replace 0x0357B7E560260945c62b99C002eFC4f5B149eC2a with your USD token contract address. The code is shown here: 
LCM = LCMaster(msg.sender);
ERC20Interface = ERC20(0x0357B7E560260945c62b99C002eFC4f5B149eC2a);
}
  1. Next, in the following code block, we define the modifiers for our methods. The onlyAuth modifier allows access only to the bank, Buyer, and Seller relevant to the LC:
modifier onlyAuth {
if (msg.sender!=bank && msg.sender!=LCnew.BuyerAcc && msg.sender!=LCnew.SellerAcc) revert();
_;
}
  1. The following modifier, onlySeller, is for the settlement method. It allows only the Seller's account address to invoke a settlement request on the LC:
modifier onlySeller {
if (msg.sender!=LCnew.SellerAcc) revert();
_;
}
  1. The following event, SettleLCSuccessfulis triggered when a settlement request is processed successfully and funds are transferred to the Seller's account:
event SettleLCSuccessful(
uint LCNum,
address SAcc,
uint Amt,
uint IAmt,
bytes2 Stat,
bytes32 DocH
);

The preceding event prints the LC number, the Seller's account from which the settlement request was made, the amount asked for settlement, the initial amount, the current status of the LC, and the document hash provided for verification during settlement.

  1. Now, let's start writing our functions. We start with the viewLCDetails () function, shown in the following code block:
function viewLCdetails() public onlyAuth view returns (uint, address, address, uint,uint, bytes2, uint, uint, bytes32)
{

The onlyAuth modifier in the preceding code block ensures only the bank, Buyer, and Seller accounts can access it. The return parameter types are defined as per the original declaration in our LCnew structure.

  1. Next, we return the requisite data, as shown in the following code block:
return ( LCnew.LCNo,
LCnew.BuyerAcc,
LCnew.SellerAcc,
LCnew.Amount,
LCnew.IniAmount,
LCnew.Status,
LCnew.DOIssue,
LCnew.DOExpiry,
LCnew.DocHash
);
}

The method returns the LC details—specifically, the following parameters:

  • LC number (LCNo
  • Buyer's Ethereum account address (BuyerAcc
  • Seller's Ethereum account address (SellerAcc
  • Amount available in escrow (Amount
  • Initial amount stored to escrow (IniAmount
  • Current status of the LC (I—Issued, P—Partially Settled, S—Settled)
  • DOI of the LC (DOIssue)
  • DOE of the LC (DOExpiry)
  • Hash of the document submitted by the Seller during settlement (DocHash)
  1. The following method, settleLCis invoked by the Seller during a settlement request:
function settleLC(uint SettleAmt, bytes32 DocH) public onlySeller 
{

It takes the settlement amount (SettleAmt) and document hash (DocH) as input. The onlySeller modifier ensures only the Seller account can access it.

  1. We start by putting two require statements in place to ensure that our LC contract is valid, as shown in the following code block:
require(LCnew.DOExpiry >= now && now >= LCnew.DOIssue, "LC Expired or Invalid Date ofIssue");
require(SettleAmt > 0 && SettleAmt <= LCnew.Amount , "Invalid Settlement Amount");

From the preceding code, we can make the following observations:

  • The first require statement checks that the time at which the settlement request was sent is after the date of issue, and before or on the date of expiry of the LC.
  • In the case of an invalid date of request or an expired LC, it presents the message LC Expired or Invalid Date of Issue to the console.
  • The second require statement checks if the settlement amount sent by the seller for processing is greater than zero and if it is below the total amount available in the LC.
  1. Next, we check if the settlement amount (SettleAmt) is less than or equal to the total amount available in the escrow account. In the case of the settlement amount being less, the Seller can still proceed with a partial settlement. They are paid the settlement amount from the LC escrow, and the LC escrow amount parameter is updated to reflect the currently available funds.

If the settlement amount is equal to the total funds allocated to the LC, the entire amount is settled and transferred to the Seller's Ethereum account. The LC's status should update to 'S', indicating settled, and the amount in escrow will be set to zero. 

  1. We check the partial settlement case by verifying the settlement amount using an if clause, as shown in the following code block:
if(SettleAmt == LCnew.Amount )
{
ERC20Interface.transfer(msg.sender, SettleAmt);
LCM.modifyLC(LCnew.LCNo,0,'S');

From the preceding code, we can make the following observations:

  • If the settlement amount (SettleAmt) is equal to the total amount available under the escrow (LCNew.Amount), we send a transaction worth the escrow amount to the Seller's address.
  • This is done by calling the ERC20 transfer method using the ERC20Interface we defined earlier. The transfer method transfers the settlement amount from the LC escrow account to the Seller's account.
  • The Seller's account is identified here, through the msg.sender variable, as it holds the account of the Seller making the settlement request. 
  1. Next, we invoke the modifyLC method we created earlier in our LC Master smart contract. This invocation is done using the LC Master LCM instance we defined earlier.

The input parameters that are set are the LC number, 0 (current amount in LC after settlement), and the 'S' flag, indicating a full settlement of the LC.

  1. The following code shows the modifyLC method from LCMaster that we wrote earlier:
function modifyLC(uint LCNum, uint SettleAmt, bytes2 Stat) public 
{
LCData memory Temp;
Temp = LCDoc[LCNum];
Temp.Status = Stat;
Temp.Amount = SettleAmt;
delete LCDoc[LCNum];
LCDoc[LCNum] = Temp;
    • The modifyLC method declares a temporary object called Temp and stores the existing values of the LC.
    • It then updates the current amount (0 USD) and status (S) of the LC, as sent by the child LC contract, and updates it to the LCDoc struct array.
    • It does so by deleting the old component and replacing the new one. 
  1. It then issues an event with the new LC details after successful modification, as shown in the following code block:
emit ModifyLCSuccessful(
LCDoc[LCNum].LCNo,
LCDoc[LCNum].SellerAcc,
LCDoc[LCNum].BuyerAcc,
LCDoc[LCNum].Amount,
LCDoc[LCNum].Status);
}

The preceding event prints the LCNo, the Seller's account, the Buyer's Account, current amount, and current status.

  1. Back to our settleLC() method in the LC smart contract. After the successful execution of the transfer and update to the LC Master contract, we update the LC details in the LC smart contract, as shown in the following code block:
LCnew.Amount = 0;
LCnew.Status = 'S';
LCnew.DocHash = DocH;
}

In the preceding code, the current amount is set to 0, the status to 'S', and the document hash sent as part of the request is stored. These details can be viewed any time using the viewLCdetails() method.

  1. Lastly, the SettleLCSuccessful event is triggered, as follows:
emit SettleLCSuccessful(LCnew.LCNo,
LCnew.SellerAcc,
LCnew.Amount,
LCnew.IniAmount,
LCnew.Status,
LCnew.DocHash);

It prints the following details to the console:

  • The Seller's Ethereum account to which the funds were transferred (SellerAcc)
  • The current funds in the escrow (Amount)
  • The initial funds in the escrow (IniAmount)
  • The current status of the LC (Status)
  • The hash of the document submitted for settlement (DocHash)

If the settlement amount is less than the amount, the following else clause will be triggered:

else
{
uint currAmt = LCnew.Amount - SettleAmt
ERC20Interface.transfer(msg.sender, SettleAmt);
LCM.modifyLC(LCnew.LCNo,currAmt,'P');

From the preceding code, we can make the following observations:

  • We first calculate the current amount (currAmt), by deducting the settlement amount from the escrow amount.
  • Next, we invoke the ERC20 transfer method, using the ERC20Interface to send the settlement amount from our LC escrow account to the Seller's account. The Seller's account is identified from the system-defined msg.sender parameter.
  • The LC Master instance ( LCM ) is used to invoke the modifyLC method within the LC Master smart contract. The input parameters are the LC number (LCnew.LCNo), the current amount in the LC escrow (currAmt), and the current status ( 'P' ), to denote partial settlement.

As in the total settlement case, the modifyLC method updates the current status and current amount for the LC and triggers the ModifyLCSuccessful event. After a successful settlement, we update the LC details for our child LC contract. The new amount, the new status, and the hash of the document submitted for settlement is updated for our LCnew object, which holds the LC details, as follows:

LCnew.Amount = currAmt;
LCnew.Status = 'P';
LCnew.DocHash = DocH;

These can be viewed for recording purposes using the viewLCdetails method. Lastly, the SettleLCSuccessful event is triggered, as follows:

emit SettleLCSuccessful(LCnew.LCNo,
LCnew.SellerAcc,
LCnew.Amount,
LCnew.IniAmount,
LCnew.Status,
LCnew.DocHash);
}
}
}

The preceding code prints the following details to the console:

  • The Seller's Ethereum account to which the funds were transferred (SellerAcc)
  • The current funds in the escrow (Amount)
  • The initial funds in the escrow (IniAmount)
  • The current status of the LC (Status)
  • The hash of the document submitted for settlement (DocHash)

With that, we come to the end of our settleLC method, and the LC smart contract.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.131.178