Skip to content

albertoZurini/ETHWarsaw2024

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Crypto PoS

Web3-ready Point of Sale system for cryptocurrency transactions using NFC technology.
Supports transactions on Optimism Sepolia, Ethereum Sepolia, Celo, Celo cUSD, and Zircuit Testnet.

Overview

gif example

Crypto PoS offers a contactless payment experience using NFC (Near Field Communication) for fast and secure cryptocurrency transactions. Designed for merchants and users alike, it simplifies crypto payments by leveraging NFC tags/cards, providing a seamless and intuitive payment process.

With Crypto PoS, you can choose between two main protocols:

  1. Card Emulation Mode
    In this mode, the PoS shares address, chain ID, and transaction amount with a phone, which then processes the transaction. The PoS listens for on-chain transactions to confirm the payment using BlockScout's API.

  2. NFC Card Mode
    Users can load balance onto an NFC card and transfer funds by simply tapping it on the PoS. While this mode offers convenience, the current implementation lacks robust security measures like transaction signing, as it requires a custom smartcard. Future improvements aim to enhance security.

The system supports tax reporting by utilizing DBForest to store transaction data and zkVerify to generate zero-knowledge proofs, ensuring privacy when reporting the total amount handled.

Features

  • NFC Contactless Payments
    Enables tap-to-pay cryptocurrency transactions with NFC tags or cards.

  • Multi-chain Support
    Transactions can be made on multiple networks: Optimism Sepolia, Ethereum Sepolia, Celo Alfajores, Celo cUSD ERC20, and Zircuit Testnet.

  • ENS Integration
    Displays ENS (Ethereum Name Service) information for added trust in transactions.

  • Invoice Generation
    Merchants can generate invoices using Request Network. request network

  • Zero-Knowledge Proofs
    zkVerify integration for secure and private transaction reporting.

Problem it Solves

QR-based crypto payments, while useful, can be unreliable due to scanning issues. Crypto PoS offers a more reliable and user-friendly contactless alternative. With NFC technology, users can complete payments without relying on QR codes, enhancing convenience and speed.

Moreover, Crypto PoS aims to simplify tax reporting by using zero-knowledge proofs to share only the total amount of transactions handled, avoiding the need to disclose individual transactions to authorities.

Technologies Used

  • Solidity (for smart contract development) https://github.com/albertoZurini/ETHWarsaw2024/tree/master/PoS_smartContract
  • Optimism Sepolia, Ethereum Sepolia, Celo Alfajores, Zircuit Testnet (blockchain networks)
    <td>
    <button onclick="switchNetwork('0xaa37dc')">Switch to Optimism Sepolia</button>
    <br/>
    <button onclick="switchNetwork('0xaef3')">Switch to CELO testnet</button>
    <button onclick="switchNetwork('0xaef3', '0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1')">Switch to CELO cUSD testnet</button>
    <br/>
    <button onclick="switchNetwork('0xaa36a7')">Ethereum Sepolia</button>
    <br/>
    <button onclick="switchNetwork('0xbf03')">Zircuit</button>
    </td>
    <td>
    <button onclick="sellProduct(10, 'Product one')">Sell product 1 (price 10)</button>
    <button onclick="sellProduct(5, 'Product two')">Sell product 2 (price 5)</button>
    </td>
  • BlockScout API (for transaction confirmation)
    async function displayTransactionInfo(msg){
    let hash = msg.hash;
    let endpoint
    if(msg.celoToken){
    // Do things for cUSD
    endpoint = `https://celo-alfajores.blockscout.com/api/v2/transactions/${hash}`
    } else {
    endpoint = `https://optimism-sepolia.blockscout.com/api/v2/transactions/${hash}`
    }
    for(let i =0; i<10; i++){
    let resp = await fetch(endpoint)
    let trns = await resp.json()
    log(`Transaction status: ${trns.status}`)
    if(trns.status == "ok"){
    handleTransactionSuccessful()
    break
    } else {
    handleBeforeTransaction()
    }
    await sleep(2000)
    }
  • DBForest (for transaction storage)
    const DBNAME = "POS";
    async function setUpPG(){
    await client.connect()
    const res = await client.query('SELECT $1::text as message', ['Hello world!'])
    console.log("Postgres started successfully", res.rows[0].message) // Hello world!
    const checkDbQuery = `SELECT 1 FROM pg_database WHERE datname = '${DBNAME}'`;
    const result = await client.query(checkDbQuery);
    // Create the database if it doesn't exist
    try {
    if (result.rows.length > 0) {
    console.log(`Database '${DBNAME}' already exists.`);
    } else {
    // If database doesn't exist, create it
    const createDbQuery = `CREATE DATABASE "${DBNAME}"`;
    await client.query(createDbQuery);
    console.log(`Database '${DBNAME}' created.`);
    }
    } catch (err) {
    console.error('Error checking or creating database:', err);
    }
    // Create the table
    try {
    // Check if the table 'POS' exists
    const checkTableQuery = `
    SELECT EXISTS (
    SELECT FROM pg_tables
    WHERE schemaname = 'public' AND tablename = 'pos'
    )`;
    const tableResult = await client.query(checkTableQuery);
    if (tableResult.rows[0].exists) {
    console.log(`Table 'POS' already exists.`);
    } else {
    // Create the table 'POS' if it doesn't exist
    const createTableQuery = `
    CREATE TABLE IF NOT EXISTS POS (
    id SERIAL PRIMARY KEY,
    transactionId VARCHAR(255) NOT NULL,
    chainId VARCHAR(255) NOT NULL,
    tokenId VARCHAR(255),
    productName VARCHAR(255) NOT NULL,
    amount INTEGER NOT NULL
    );
    `;
    await client.query(createTableQuery);
    console.log(`Table 'POS' created.`);
    }
    } catch (err) {
    console.error('Error checking or creating table:', err);
    }
    await dumpPOSTable()
    //await deletePOSTable()
    /*
    await dumpPOSTable()
    await addNewEntryToPOS(1, "test", "test", "test", 10)
    await dumpPOSTable()
    */
    }
    setUpPG()
    async function dumpPOSTable() {
    try {
    // Query to select all rows from the POS table
    const query = 'SELECT * FROM POS';
    const result = await client.query(query);
    // Log the result
    console.log('Dumping table POS:');
    console.log(result.rows); // Dump all rows to the console
    } catch (err) {
    console.error('Error dumping table:', err);
    }
    }
    async function addNewEntryToPOS(transactionId, chainId, tokenId, productName, amount) {
    try {
    // Query to insert a new entry into the POS table
    const query = `
    INSERT INTO POS (transactionId, chainId, tokenId, productName, amount)
    VALUES ($1, $2, $3, $4, $5)
    RETURNING *;
    `;
    // Execute the query with the provided arguments
    const result = await client.query(query, [transactionId, chainId, tokenId, productName, amount]);
    // Log the inserted row
    console.log('New entry added to POS:');
    console.log(result.rows[0]);
    } catch (err) {
    console.error('Error adding new entry to POS:', err);
    }
    }
    async function deletePOSTable() {
    try {
    // Query to drop the POS table
    const query = 'DROP TABLE IF EXISTS POS';
    await client.query(query);
    console.log('Table POS deleted (if it existed).');
    } catch (err) {
    console.error('Error deleting table:', err);
    }
    }
  • NFC https://github.com/albertoZurini/ETHWarsaw2024/tree/master/PoS_cardEmulator/nfc_test
  • zkVerify (for zero-knowledge proofs) https://github.com/albertoZurini/ETHWarsaw2024/tree/master/PoS_cardEmulator/zkverify
  • ENS (for domain name resolution)
    </script>
    <script type="module">
    // ENS PART
    import { createPublicClient, http } from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm'
    import { sepolia } from 'https://cdn.jsdelivr.net/npm/[email protected]/chains/+esm';
    import { normalize } from 'https://cdn.jsdelivr.net/npm/[email protected]/ens/+esm';
    async function getEnsName(address){
    const client = createPublicClient({
    chain: sepolia,
    transport: http(
    'https://rpc2.sepolia.org'
    ),
    });
    const fetchedEnsName = await client.getEnsName({
    address,
    })
    const description = await client.getEnsText({
    name: fetchedEnsName,
    key: 'description',
    });
    const avatar = await client.getEnsText({
    name: fetchedEnsName,
    key: 'avatar',
    });
    return {fetchedEnsName, description, avatar}
    }
    module.getEnsName = getEnsName
    </script>
  • Request Network (for invoice generation) https://github.com/albertoZurini/ETHWarsaw2024/tree/master/PoS_cardEmulator/invoicing/invoicing-template
  • Docker (for zkVerify integration) https://github.com/albertoZurini/ETHWarsaw2024/tree/master/PoS_cardEmulator/zkverify/Docker

Setup Instructions

  1. Clone the repository:

    git clone https://github.com/albertoZurini/ETHWarsaw2024.git
    cd ETHWarsaw2024
  2. Install Dependencies:

    • Install required packages for your environment (e.g., Docker for zkVerify).
    • Run npm i
    • Configure secrets in keys.js
  3. Deploy the Smart Contracts:

    • Use the provided Solidity contracts and deploy them to the supported networks.
  4. Run the Application:

    • Set up your NFC reader, connect to the selected blockchain network, and start the PoS system.

Video Demo

Check out a live demo of Crypto PoS in action: YouTube Demo

Devfolio

Check out this project on Devfolio

Team

I did hack solo for this hackathon.

Next steps

  1. Develop a custom Smartcard able to sign a challenge coming from the smart contract.
  2. Develop a hardware able to take in both contact-less payment types (crypto and FIAT).

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published