Decentralized KYC Verification Process for Banks
Prashant Upadhyaya
Post-Graduate Certificate Program in Blockchain
Indian Institute of Technology, Kanpur
drprashant79@[Link]
I. SOURCE CODE
Ethereum Smart Contract file: [Link]
// SPDX-License-Identifier: MIT
// compiler version must be greater than or equal to 0.8.10 and less than 0.9.0
pragma solidity ^0.8.11;
contract kycpau {
// Struct Customer
// custName - username of the customer
// custData - customer data
// rating - rating given to customer given based on regularity
// upvotes - number of upvotes recieved from banks
// bank - address of bank that validated the customer account
struct Customer {
string custName;
string custData;
uint rating;
uint upvotes;
address bank;
string password;
}
// Struct Bank
// bankName - bankName of the bank
// ethAddress - ethereum address of the bank
// rating - rating based on number of valid/invalid verified accounts
// KYC_count - number of KYCs verified by the bank
struct Bank {
string bankName;
address ethAddress;
uint rating;
uint KYC_count;
string regNumber;
}
struct Request {
string custName;
address bankAddress;
bool isAllowed;
}
// list of all customers
Customer[] allCustomers;
// list of all Banks
Bank[] allBanks;
// list of all KYC Requests
Request[] allRequests;
function ifAllowed(string memory CustName, address bankAddress) public payable returns(bool) {
for(uint i = 0; i < [Link]; ++i) {
if(stringsEqual(allRequests[i].custName, CustName) && allRequests[i].bankAddress == bankAddress && allRequests[i].isAllowed)
{
return true;
}
}
return false;
}
function getBankRequests(string memory CustName, uint ind) public payable returns(address) {
uint j = 0;
for(uint i=0;i<[Link];++i) {
if(stringsEqual(allRequests[i].custName, CustName) && j == ind && allRequests[i].isAllowed == false) {
return allRequests[i].bankAddress;
}
j ++;
}
return 0x4Ca570E48943baF02BF4D38af2189cE0208f9065;
}
function addRequest(string memory CustName, address bankAddress) public payable {
for(uint i = 0; i < [Link]; ++ i) {
if(stringsEqual(allRequests[i].custName, CustName) && allRequests[i].bankAddress == bankAddress) {
return;
}
}
[Link];
allRequests[[Link] - 1] = Request(CustName, bankAddress, false);
}
function allowBank(string memory CustName, address bankAddress, bool ifallowed) public payable {
for(uint i = 0; i < [Link]; ++ i) {
if(stringsEqual(allRequests[i].custName, CustName) && allRequests[i].bankAddress == bankAddress) {
if(ifallowed) {
allRequests[i].isAllowed = true;
} else {
for(uint j=i;j<[Link]-2; ++j) {
allRequests[i] = allRequests[i+1];
}
[Link];
}
return;
}
}
}
// internal function to compare strings
function stringsEqual(string storage _a, string memory _b) internal returns (bool) {
bytes storage a = bytes(_a);
bytes memory b = bytes(_b);
if ([Link] != [Link])
return false;
// @todo unroll this loop
for (uint i = 0; i < [Link]; i ++)
{
if (a[i] != b[i])
return false;
}
return true;
}
// function to check access rights of transaction request sender
function isPartOfOrg() public payable returns(bool) {
for(uint i = 0; i < [Link]; ++ i) {
if(allBanks[i].ethAddress == [Link])
return true;
}
return false;
}
// function that adds an Bank to the network
// returns 0 if successfull
// returns 7 if no access rights to transaction request sender
// no check on access rights if network strength in zero
function addBank(string memory custName, address eth, string memory regNum) public payable returns(uint) {
if([Link] == 0 || isPartOfOrg()) {
[Link];
allBanks[[Link] - 1] = Bank(custName, eth, 200, 0, regNum);
return 0;
}
return 7;
}
// function that removes an Bank from the network
// returns 0 if successful
// returns 7 if no access rights to transaction request sender
// returns 1 if Bank to be removed not part of network
function blockBank(address eth) public payable returns(uint) {
if(!isPartOfOrg())
return 7;
for(uint i = 0; i < [Link]; ++ i) {
if(allBanks[i].ethAddress == eth) {
for(uint j = i+1;j < [Link]; ++ j) {
allBanks[i-1] = allBanks[i];
}
[Link];
return 0;
}
}
return 1;
}
// function to add a customer profile to the database
// returns 0 if successful
// returns 7 if no access rights to transaction request sender
// returns 1 if size limit of the database is reached
// returns 2 if customer already in network
function addCustomer(string memory CustName, string memory custData) public payable returns(uint) {
if(!isPartOfOrg())
return 7;
// throw error if userbankName already in use
for(uint i = 0;i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName))
return 2;
}
[Link];
// throw error if there is overflow in uint
if([Link] < 1)
return 1;
allCustomers[[Link]-1] = Customer(CustName, custData, 100, 0, [Link], "null");
updateRating([Link],true);
return 0;
}
// function to remove fraudulent customer profile from the database
// returns 0 if successful
// returns 7 if no access rights to transaction request sender
// returns 1 if customer profile not in database
function blockCustomer(string memory CustName) public payable returns(uint) {
if(!isPartOfOrg())
return 7;
for(uint i = 0; i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName)) {
address a = allCustomers[i].bank;
for(uint j = i+1;j < [Link]; ++ j) {
allCustomers[i-1] = allCustomers[i];
}
[Link];
updateRating(a,false);
// updateRating([Link], true);
return 0;
}
}
// throw error if custName not found
return 1;
}
// function to modify a customer profile in database
// returns 0 if successful
// returns 7 if no access rights to transaction request sender
// returns 1 if customer profile not in database
function modifyCustomer(string memory CustName,string memory custData) public payable returns(uint) {
if(!isPartOfOrg())
return 7;
for(uint i = 0; i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName)) {
allCustomers[i].custData = custData;
allCustomers[i].bank = [Link];
return 0;
}
}
// throw error if custName not found
return 1;
}
// function to return customer profile data
function viewCustomer(string memory CustName) public payable returns(string memory) {
if(!isPartOfOrg())
return "Access denied!";
for(uint i = 0; i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName)) {
return allCustomers[i].custData;
}
}
return "Customer not found in database!";
}
// function to modify customer rating
function updateRatingCustomer(string memory CustName, bool ifIncrease) public payable returns(uint) {
for(uint i = 0; i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName)) {
//update rating
if(ifIncrease) {
allCustomers[i].upvotes ++;
allCustomers[i].rating += 100/(allCustomers[i].upvotes);
if(allCustomers[i].rating > 500) {
allCustomers[i].rating = 500;
}
}
else {
allCustomers[i].upvotes --;
allCustomers[i].rating -= 100/(allCustomers[i].upvotes + 1);
if(allCustomers[i].rating < 0) {
allCustomers[i].rating = 0;
}
}
return 0;
}
}
// throw error if bank not found
return 1;
}
// function to update Bank rating
// bool true indicates a succesfull addition of KYC profile
// false indicates detection of a fraudulent profile
function updateRating(address bankAddress,bool ifAdded) public payable returns(uint) {
for(uint i = 0; i < [Link]; ++ i) {
if(allBanks[i].ethAddress == bankAddress) {
//update rating
if(ifAdded) {
allBanks[i].KYC_count ++;
allBanks[i].rating += 100/(allBanks[i].KYC_count);
if(allBanks[i].rating > 500) {
allBanks[i].rating = 500;
}
}
else {
// allBanks[i].KYC_count --;
allBanks[i].rating -= 100/(allBanks[i].KYC_count + 1);
if(allBanks[i].rating < 0) {
allBanks[i].rating = 0;
}
}
return 0;
}
}
// throw error if bank not found
return 1;
}
// function to validate bank log in
// returns null if userbankName or password not correct
// returns bank bankName if correct
function checkBank(string memory CustName, address password) public payable returns(string memory) {
for(uint i = 0; i < [Link]; ++ i) {
if(allBanks[i].ethAddress == password && stringsEqual(allBanks[i].bankName, CustName)) {
return "0";
}
}
return "null";
}
function checkCustomer(string memory CustName, string memory password) public payable returns(bool) {
for(uint i = 0; i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName) && stringsEqual(allCustomers[i].password, password)) {
return true;
}
if(stringsEqual(allCustomers[i].custName, CustName)) {
return false;
}
}
return false;
}
function setPassword(string memory CustName, string memory password) public payable returns(bool) {
for(uint i=0;i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName) && stringsEqual(allCustomers[i].password, "null")) {
allCustomers[i].password = password;
return true;
}
}
return false;
}
// All getter functions
function getBankName(address ethAcc) public payable returns(string memory) {
for(uint i = 0; i < [Link]; ++ i) {
if(allBanks[i].ethAddress == ethAcc) {
return allBanks[i].bankName;
}
}
return "null";
}
function getBankEth(string memory custName) public payable returns(address) {
for(uint i = 0; i < [Link]; ++ i) {
if(stringsEqual(allBanks[i].bankName, custName)) {
return allBanks[i].ethAddress;
}
}
return 0x4Ca570E48943baF02BF4D38af2189cE0208f9065;
}
function getCustomerBankName(string memory CustName) public payable returns(string memory) {
for(uint i = 0;i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName)) {
return getBankName(allCustomers[i].bank);
}
}
}
function getBankReg(address ethAcc) public payable returns(string memory) {
for(uint i = 0; i < [Link]; ++ i) {
if(allBanks[i].ethAddress == ethAcc) {
return allBanks[i].regNumber;
}
}
return "null";
}
function getBankKYC(address ethAcc) public payable returns(uint) {
for(uint i = 0; i < [Link]; ++ i) {
if(allBanks[i].ethAddress == ethAcc) {
return allBanks[i].KYC_count;
}
}
return 0;
}
function getBankRating(address ethAcc) public payable returns(uint) {
for(uint i = 0; i < [Link]; ++ i) {
if(allBanks[i].ethAddress == ethAcc) {
return allBanks[i].rating;
}
}
return 0;
}
function getCustomerBankRating(string memory CustName) public payable returns(uint) {
for(uint i = 0;i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName)) {
return getBankRating(allCustomers[i].bank);
}
}
}
function getCustomerRating(string memory CustName) public payable returns(uint) {
for(uint i = 0; i < [Link]; ++ i) {
if(stringsEqual(allCustomers[i].custName, CustName)) {
return allCustomers[i].rating;
}
}
return 0;
}