EternaBlockMemorials
Back to Home
Documentation

Memorials Protocol

Eternal memory on-chain. Create memorials

Purpose

Every life is a story. When someone leaves, we are left with the need to remember—to hold a name, a face, a span of years, and the weight of what they meant. Memorials Protocol exists so that remembrance is not left to chance. It offers a place where a life can be inscribed on the chain: a name, birth and death dates, a few words, an image. Once written, it stays. No server goes down, no link rots. It becomes part of a shared, permanent ledger.

Flowers have always been a language of honor and care. Here, each "flower" is a small tribute in USDT—a gesture that says "you are not forgotten." When someone pays tribute, they are not only leaving a mark; they are also supporting the people who keep that memory alive. The protocol splits each tribute between the memorial owner, the protocol, and an optional partner (ambassador), so that both memory and meaning can be sustained over time.

We built this for anyone who has lost someone, or who wants to leave a trace that outlasts a single machine or a single era. No gatekeepers, no permissions—only a minimal, dignified way to say: this person existed, and they mattered.

Technically: memorials and tributes live on BSC. Data is immutable; tributes accumulate as flowers and fund the memorial owner. The goal is permissionless, eternal remembrance.

Basic operations

  • Create a memorial

    Call createMemorial(name, birthTimestamp, deathTimestamp, description, imageBase64). You become the owner. The memorial gets the next numeric id (0, 1, 2, …).

  • Browse memorials

    Use memorialCount() and getMemorial(memorialId) to list and display memorials. No off-chain index required.

  • Pay tribute

    Approve USDT to the protocol, then call tribute(memorialId, quantity, partner). Each flower is 2 USDT. 5% goes to the protocol; if partner is not zero, 2% goes to that address; the rest goes to the memorial owner.

  • Withdraw (owner)

    Memorial owners call ownerWithdraw(memorialId) to pull their accumulated USDT balance.

Ambassador program

You can build your own UI (landing page, app, or integration) and direct users to pay tribute. When they call tribute(memorialId, quantity, partner), pass your wallet address as the partner argument.

If partner is not the zero address, 2% of each tribute is sent to that address. So you earn 2% of every tribute that flows through your link or UI. No need to ask permission: just use the same contract and set partner to your address.

Example: tribute(memorialId, 5, 0xYourAddress) → you receive 2% of 10 USDT = 0.2 USDT per call.

Contracts & ABI

Core addresses (configure in .env)

MemorialProtocol
0x3Be2d830202209d8068B9AA9c7A62F9C4BeCa81e
USDT (ERC20)
0x55d398326f99059ff775485246999027b3197955

Main functions

  • createMemorial(name, birthTimestamp, deathTimestamp, description, imageBase64) → memorialId
  • tribute(memorialId, quantity, partner)
  • getMemorial(memorialId) → (owner, name, birthTimestamp, deathTimestamp, description, imageBase64, totalFlowers, ownerBalance)
  • memorialCount() → uint256
  • ownerWithdraw(memorialId)

MemorialProtocol ABI (minimal)

[
  {
    "inputs": [
      {
        "name": "name",
        "type": "string"
      },
      {
        "name": "birthTimestamp",
        "type": "uint256"
      },
      {
        "name": "deathTimestamp",
        "type": "uint256"
      },
      {
        "name": "description",
        "type": "string"
      },
      {
        "name": "imageBase64",
        "type": "string"
      }
    ],
    "name": "createMemorial",
    "outputs": [
      {
        "name": "memorialId",
        "type": "uint256"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "name": "memorialId",
        "type": "uint256"
      },
      {
        "name": "quantity",
        "type": "uint256"
      },
      {
        "name": "partner",
        "type": "address"
      }
    ],
    "name": "tribute",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "name": "memorialId",
        "type": "uint256"
      }
    ],
    "name": "ownerWithdraw",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "memorialCount",
    "outputs": [
      {
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "name": "memorialId",
        "type": "uint256"
      }
    ],
    "name": "getMemorial",
    "outputs": [
      {
        "name": "owner",
        "type": "address"
      },
      {
        "name": "name",
        "type": "string"
      },
      {
        "name": "birthTimestamp",
        "type": "uint256"
      },
      {
        "name": "deathTimestamp",
        "type": "uint256"
      },
      {
        "name": "description",
        "type": "string"
      },
      {
        "name": "imageBase64",
        "type": "string"
      },
      {
        "name": "totalFlowers",
        "type": "uint256"
      },
      {
        "name": "ownerBalance",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]