Technical Architecture

Deep dive into MakaPay's smart contract architecture, deterministic addresses, and cross-chain capabilities.


Smart Contract Overview

MakaPay uses a minimal proxy pattern with CREATE2 for gas-efficient, deterministic payment addresses.

┌─────────────────────────────────────────────────────────────┐
│                    MakaChain (Hub)                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │  GasTank    │  │PaymentNotifier│ │ TrustedOracle       │  │
│  │  (Balances) │  │  (Events)    │  │ (Price Feeds)       │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│              Payment Chains (Ethereum, Polygon, BSC)        │
│  ┌─────────────────────────┐  ┌───────────────────────────┐ │
│  │ PaymentWalletFactory    │  │ PaymentWalletImplementation│ │
│  │ (Deploys wallets)       │  │ (Template contract)        │ │
│  └─────────────────────────┘  └───────────────────────────┘ │
│                                                             │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐            │
│  │PaymentWallet│ │PaymentWallet│ │PaymentWallet│  ...       │
│  │  (Proxy 1)  │ │  (Proxy 2)  │ │  (Proxy N)  │            │
│  └─────────────┘ └─────────────┘ └─────────────┘            │
└─────────────────────────────────────────────────────────────┘

PaymentWalletFactory

The Factory contract deploys payment wallets using the CREATE2 opcode for deterministic addresses.

Key Functions

computeAddress()

Pre-computes the payment wallet address before deployment.

Parameters:

  • orderId: Unique payment identifier

  • merchant: Address to receive funds

  • token: ERC20 token contract address

  • feeRecipient: Address receiving protocol fees

  • feeAmount: Fee amount to deduct

Returns: The deterministic address where the wallet will be deployed.

createPaymentWallet()

Deploys a payment wallet at the pre-computed address.

What happens:

  1. Computes salt from all parameters

  2. Deploys minimal proxy via CREATE2

  3. Initializes the proxy with payment details

  4. Automatically calls withdraw() to settle funds

Address Computation (CREATE2)

The wallet address is computed as:

Where salt is:


PaymentWalletImplementation

The implementation contract contains the logic that all payment wallet proxies delegate to.

Storage Variables

Key Functions

initialize()

Called once when the proxy is deployed.

withdraw()

Settles funds to the merchant.

Logic:

  1. Get token balance of wallet

  2. Calculate fee (proportional if partial payment)

  3. Transfer fee to feeRecipient

  4. Transfer remainder to merchant

  5. Call merchant's onPaymentReceived() callback (if contract)


EIP-1167 Minimal Proxy Pattern

Instead of deploying full contract bytecode for each payment, we use minimal proxies.

Benefits

Aspect
Full Contract
Minimal Proxy

Deployment Gas

~500,000

~50,000

Bytecode Size

~5KB

~45 bytes

Functionality

Full

Delegates to implementation

How It Works

The minimal proxy is just 45 bytes:

All calls to the proxy are delegated to the implementation contract.


Nick's Method & Cross-Chain Recovery

What is Nick's Method?

Nick's Method (named after Nick Johnson) uses CREATE2 to deploy contracts at the same address across different blockchains.

Why It Matters for MakaPay

Problem: A customer sends USDT on Polygon to an address, but the merchant expected payment on Ethereum.

Traditional Approach: Funds are lost. The address on Ethereum is either:

  • Empty (no contract)

  • A different contract

  • Inaccessible

MakaPay Approach: Because we use CREATE2 with identical parameters:

  1. The address is the same on all chains

  2. We can deploy the same wallet on any chain

  3. Funds can be recovered by deploying on the correct chain

How Cross-Chain Recovery Works

Technical Requirements for Same Address

For the address to be identical across chains:

  1. Same Factory Address: Factory must be at same address on all chains

  2. Same Implementation: Implementation bytecode must be identical

  3. Same Parameters: orderId, merchant, token address*, feeRecipient, feeAmount

*Token addresses may differ across chains, but the computation uses the original chain's token address.

Deploying Factory at Same Address

We use a keyless deployment transaction (Nick's original method):


Payment Flow (On-Chain)

Step 1: Address Computation

Step 2: Customer Payment

Step 3: Settlement

Step 4: Callback (Optional)

If merchant is a contract implementing IPaymentReceiver:

The wallet calls this after settlement, enabling:

  • Automatic order fulfillment

  • Inventory updates

  • Event logging


PaymentNotifier (Gasless Settlements)

For gasless payments, the PaymentNotifier records settlements on MakaChain.

Purpose

  • Single source of truth for all settlements

  • Emits events for off-chain indexing

  • Collects processing fee ($0.10)

Contract Interface

Event


Security Measures

Reentrancy Protection

All fund-moving functions use nonReentrant modifier:

SafeERC20

All token transfers use OpenZeppelin's SafeERC20:

One-Time Initialization

Proxies can only be initialized once:

Nonce Validation (Gas Tank)

Deposits use nonces to prevent replay attacks:


Contract Addresses

MakaChain Mainnet (777178)

Contract
Address

GasTank

0x...

PaymentNotifier

0x...

TrustedOracle

0x...

USDT

0x30C28E393E0732335235685B345c95E6465Ad8A5

Payment Chains

Chain
Factory
Implementation

Ethereum

0x...

0x...

Polygon

0x...

0x...

BSC

0x...

0x...

MakaChain

0x...

0x...

Addresses are identical across all chains due to Nick's Method deployment.


Upgradeability

Factory & Implementation

  • Not upgradeable by design

  • New versions deploy as new contracts

  • Existing payments continue to work

  • Ensures immutability and trust

GasTank

  • Upgradeable by owner

  • Emergency functions for edge cases

  • Multi-sig control recommended

Last updated