Peer-to-Peer Transactions: Exploring a PayPal-like Smart Contract on the Blockchain

Peer-to-Peer Transactions: Exploring a PayPal-like Smart Contract on the Blockchain

In this blog post, we'll discuss a Solidity smart contract designed for Decentralized Peer-to-Peer Crypto Payments PayPal Smart Contract. This contract facilitates and enable users to send and receive funds along with a custom message in a decentralized manner, eliminating the need for intermediaries and enhancing the overall security of transactions.

Let's examine the smart contract I created for the D-PayPal project, which is available on my GitHub.

Link to Smart Contract -> https://github.com/AdityaB1152/CryptoPal/blob/master/Smart%20Contract/contracts/PayPal.sol

Key Components:

  1. Owner and User Management: The contract starts by assigning an owner, the entity deploying the contract. In the smart contract, there is someone in charge, called the "owner." This owner is the person who created and deployed the smart contract on the Ethereum blockchain. They have special privileges to manage and control certain aspects of the contract.

     address public owner;
    
     constructor(){
         owner = msg.sender;
     }
    
  2. Structures for Requests and Transactions: The contract utilizes two essential structures: request and sendReceive. The request structure represents a financial request made by a user, while the sendReceive structure captures the details of a transaction, including actions such as sending or receiving funds.

    a. request structure:

    Represents a financial request made by a user, containing the requester's address, amount, message, and name.

     struct request {
         address requestor;
         uint256 amount;
         string message;
         string name;
     }
    

    b. sendReceive structure:

    Captures the details of a transaction, including the action (send or receive), amount, message, other party's address, and other party's name.

     struct sendReceive {
         string action;
         uint256 amount;
         string message;
         address otherPartyAddress;
         string otherPartyName;
     }
    
  3. Username Mapping: The contract includes a username mapping feature, allowing users to associate a unique username with their Ethereum address. This enhances user experience by providing a recognizable identity on the blockchain.

     struct username {
         string name;
         bool hasName;
     }
    
     mapping (address => username) names;
    
  4. Functions for User Interaction:

    a.addName Function:

    Allows users to add a username to their Ethereum address.

     function addName(string memory _name) public {
         username storage newUserName = names[msg.sender];
         newUserName.name = _name;
         newUserName.hasName = true;
     }
    

    b. createRequest Function:

    Enables users to initiate financial requests, specifying the recipient, amount, and an optional message.

     function createRequest(address user, uint256 _amount, string memory _message) public {
          request memory newRequest;
             newRequest.requestor = msg.sender;
             newRequest.amount = _amount;
             newRequest.message = _message;
    
             if(names[msg.sender].hasName){
                 newRequest.name = names[msg.sender].name;
             }
             requests[user].push(newRequest);
     }
    

    c. payRequest Function: Users can make payments in Ether to fulfill a specific request securely.

    ```solidity function payRequest(uint256 _request) public payable { require(_request < requests[msg.sender].length , "No Such Requests"); request[] storage myRequests = requests[msg.sender]; request storage payableRequest = myRequests[_request];

    uint256 toPay = payableRequest.amount * 1000000000000000000; require(msg.value == (toPay) , "Pay Correct Amount");

    payable(payableRequest.requestor).transfer(msg.value);

    addHistory(msg.sender , payableRequest.requestor , payableRequest.amount , payableRequest.message);

myRequests[_request] = myRequests[myRequests.length - 1]; myRequests.pop();
}


5. Transaction History\*\*:\*\* The contract maintains a comprehensive transaction history through the `history` mapping. Each transaction includes details such as the action (send or receive), amount, message, and the involved parties' information.

    ```solidity
    mapping (address => sendRecive[]) history;

     function addHistory(address sender , address receiver, uint256 _amount, string memory _message) private {

        sendRecive memory newSend;
        newSend.action = "Send";
        newSend.amount = _amount;
        newSend.message = _message;
        newSend.otherPartyAddress = receiver;

        if(names[receiver].hasName){
            newSend.otherPartyName = names[receiver].name;
        }

        history[sender].push(newSend);
        sendRecive memory newReceive;
        newReceive.action = "Receive";
        newReceive.amount = _amount;
        newReceive.message = _message;
        newReceive.otherPartyAddress = sender;

        if(names[sender].hasName){
            newReceive.otherPartyName = names[sender].name;
        }

        history[receiver].push(newReceive);

        }
  1. View Functions:

    • getMyRequests: Users can retrieve a list of all pending requests sent to them, including details such as the requester's address, amount, message, and username (if available).

        function getMyRequests(address _user) public view returns(address[], uint256[], string[], string[]) {
            address[] memory addrs = new address[](requests[_user].length);
                uint256[] memory amnt = new uint256[](requests[_user].length);
                string[] memory msge = new string[](requests[_user].length);
                string[] memory nme = new string[](requests[_user].length);
      
                for (uint i = 0; i < requests[_user].length; i++) {
                    request storage myRequests = requests[_user][i];
                    addrs[i] = myRequests.requestor;
                    amnt[i] = myRequests.amount;
                    msge[i] = myRequests.message;
                    nme[i] = myRequests.name;
                }
      
                return (addrs, amnt, msge, nme);
        }
      
    • getMyHistory: Users can view their complete transaction history, gaining insights into both sent and received transactions.

        function getMyHistory(address _user) public view returns(sendRecive[] memory) {
            return history[_user];
        }
      
    • getMyName: Users can retrieve their associated username, if previously set.

    •       function getMyName(address _user) public view returns(username memory) {
                return names[_user];
            }
      

      The PayPal smart contract demonstrates how Solidity can be used to create a simple yet powerful peer-to-peer payment system on the Ethereum blockchain. Users can set usernames, create payment requests, fulfill requests, and view their transaction history. This contract provides a foundation for building decentralized finance applications and showcases the potential of blockchain technology in facilitating secure and transparent financial transactions.