Chainvoice is a decentralized invoicing dApp for EVM-compatible chains. Create, send and pay invoices on-chain in the network's native coin or any ERC-20 token, with invoice details encrypted end to end. The contract has no owner and isn't upgradeable, and it can be deployed to any EVM chain. Live deployments are listed in Deployments.md.
- Overview
- Features
- Project Structure
- Getting Started
- Frontend Setup
- Run with Docker
- Smart Contract Testing
- Deploy to an EVM Chain
- Environment Variables
- Community and Support
Chainvoice transforms traditional invoicing by leveraging blockchain technology to create a trustless, automated payment system. Users can create invoices, manage payments, and track transaction history with complete transparency and security.
- Decentralized Invoice Creation - Create and manage invoices on-chain
- Multi-Token Support - Pay using native currency or ERC-20 tokens
- Immutable Records - Verifiable transaction history and status tracking
- Treasury Management - Built-in fee management for platform sustainability
- Privacy Protection - Encrypted invoice data with access control
- User-Friendly Interface - Intuitive web application with wallet integration: browser wallets connect through WalletLink (EIP-6963), with no WalletConnect relay or project ID
Chainvoice/
├── frontend/ # Web application (UI/UX, wallet integration)
├── contracts/ # Solidity smart contracts (core invoicing logic)
├── docs/ # Documentation and guides
└── README.md # This file
- Fork the repository
- Clone your fork
git clone https://github.com/YOUR_USERNAME/Chainvoice.git
cd Chainvoice
-
Navigate to frontend directory
cd frontend -
Install dependencies
npm install -
Start development server
npm run dev -
Open application Navigate to
http://localhost:5173in your browser
Prefer containers? One command brings up the frontend together with a ThruBox relay, which invoice sending and receiving depend on — no Node.js install, and no second repository to clone:
cp frontend/.env.example frontend/.env
docker buildx build -t chainvoice/thrubox-relay:main "https://github.com/AOSSIE-Org/ThruBox-Server.git#main"
docker compose up --buildThe app is then at http://localhost:5173 and the relay at
http://localhost:3000. See docs/docker.md for the full
guide, including the production profile that serves the built bundle behind
nginx.
Prerequisites: Foundry must be installed
-
Navigate to contracts directory
cd contracts -
Run test suite
forge test -
Run tests with verbosity (optional)
forge test -vvv
The same contract and deploy script work on any EVM chain.
- Foundry installed
- A wallet funded with the chain's native coin
- An RPC URL for the chain
-
Configure environment variables
cp contracts/.env.example contracts/.env
Edit contracts/.env with your actual values -
Compile contracts
cd contracts
forge build -
Load environment variables
source .env -
Deploy
The script readsDEV_ADDRESSandDEV_FEE_RECEIVER(both required, non-zero) and an optionalDEV_FEE_WEI(default0.0005 ether, must not be0) from.env, and passes them to the constructor. Thedevaddress setsdevFeeanddevFeeReceiverand hands its own role over in two steps (proposeDev, thenacceptDevfrom the new address), so use a multisig;devFeeReceiverreceives withdrawn fees. The compiler targetsevm_version = "london"withvia_ir(seecontracts/foundry.toml), so one bytecode also runs on chains that have not adopted newer EVM upgrades.
RPC_URL=https://your-chain-rpc.example # the chain's RPC endpoint
forge script script/Chainvoice.s.sol:DeployChainvoice --rpc-url "$RPC_URL" --account deployer --broadcastChain-specific flags:
- No EIP-1559 (no base fee): add
--legacy, orforge scriptfails withunsupported feature: eip1559. - Verification (recommended): add
--verifyon a chain Etherscan supports (needsETHERSCAN_API_KEY). For a chain with a Blockscout explorer, add--verify --verifier blockscout --verifier-url "$EXPLORER_URL/api/"instead, withEXPLORER_URLset to the explorer's base URL (no key needed). - Higher on-chain gas than forge simulates (Sepolia, for example): add
--gas-estimate-multiplier 800. - Block gas limit: a full 30-invoice batch needs about 6.2M gas, so the chain's block gas limit should be at least 8M.
After deploying, record the address in Deployments.md.
-
Configure frontend
cp frontend/.env.example frontend/.env
Edit frontend/.env and set the variable for the chain you deployed to — the frontend readsVITE_CONTRACT_ADDRESS_<chainId>, not a single shared variable, for example:
VITE_CONTRACT_ADDRESS_=your_deployed_contract_address_here
See Environment Variables for the full list. -
Restart frontend development server
cd frontend
npm run dev
#Ethereum Sepolia (11155111)
VITE_CONTRACT_ADDRESS_11155111=0x65eb0ca96f972c5a0cdaa623a5b54650e499df5b
#Ethereum Classic (61) — blank until redeployed, see note below
VITE_CONTRACT_ADDRESS_61=
#Polygon Mainnet (137) — blank until redeployed, see note below
VITE_CONTRACT_ADDRESS_137=
⚠️ Renaming the key registry functions changed their selectors, so only a contract deployed from the currentcontracts/src/Chainvoice.solwill answer. The Sepolia address above is such a deployment — see Deployments.md. Keys registered against an earlier deployment do not carry over; those users must register again.
⚠️ Ethereum Classic and Polygon are left blank on purpose. Both still run the v1 contract, which stores invoice payloads on-chain as strings and has no public key registry, so it does not match the current ABI. The app treats any non-empty address as supported, so filling these in would send calls those contracts cannot decode. Populate them only after redeploying.
⚠️ Security Note: Never commit.envfiles to version control. Keep your private keys secure.
Invoice payloads travel encrypted over a ThruBox relay, configured with:
VITE_RELAY_URL=http://localhost:3000
VITE_RELAY_API_KEY=
VITE_RELAY_TIMEOUT_MS=VITE_RELAY_URL— in development this is the target the Vite dev server proxies/relayto, so the browser stays same-origin. In production, either an absolutehttps://URL (which requires CORS on the relay) or a path such as/relaythat your host rewrites to it (Vercel rewrites, Netlify redirects, nginxproxy_pass), which avoids CORS entirely.VITE_RELAY_API_KEY— only needed if the relay setssecurity.api_key. This is not a secret: Vite inlines everyVITE_-prefixed variable into the built JavaScript, so any visitor can read it. Treat it as a spam speed-bump, not access control. To keep a relay key private, proxy relay calls server-side and inject it there.VITE_RELAY_TIMEOUT_MS— request timeout, default15000. Raise it (around60000) on hosts that suspend idle instances: a cold start can take most of a minute, and sends are deliberately not retried, so a timeout means an undelivered invoice.
Stores only keccak256 of the invoice data on-chain and exposes the public key
registry. Addresses are tracked in Deployments.md.
- Ethereum Sepolia (11155111)
0x65eb0ca96f972c5a0cdaa623a5b54650e499df5b
Stores the invoice payload on-chain as strings. Superseded, kept for reference.
- Ethereum Sepolia (11155111)
0x54a542dCDC306eE281b5De4613EcEfe6e6ABc562 - Ethereum Classic (61)
0xD044A85a5daC307217B9bF313A90E8a60AF7DdCe - Polygon Mainnet (137)
0xD044A85a5daC307217B9bF313A90E8a60AF7DdCe
Release: release v1
Join our community for support, updates, and discussions:
- Telegram - t.me/StabilityNexus
- Discord - discord.gg/YzDKeEfWtS
- X (Twitter) - @StabilityNexus
- Stable Viewpoints - viewpoints.stability.nexus
- LinkedIn - linkedin.com/company/stability-nexus
- YouTube - youtube.com/@StabilityNexus
We welcome contributions! Please read our contributing guidelines and submit pull requests for any improvements.
Before making or updating any smart contract changes, please review the Smart Contract Contribution Guidelines to ensure compliance with testing, design, and review requirements.
Built with ❤️ by Stability Nexus.

