BlockLucky Documentation officielle GitHub

Référence de BlockLuckyPOAP

Cette page liste chaque fonction, événement et erreur de BlockLuckyPOAP, le badge de participation non transférable. Les tableaux sont générés depuis l'ABI embarquée par le backend, backend/src/blockchain/abi/BlockLuckyPOAP.json, et depuis le source Solidity. Le fonctionnement est expliqué dans Badge POAP.

Lire les tableaux

  • Le contrat ne déclare que quatre fonctions (mintBadge, setBaseUri, tokenURI, supportsInterface) et quatre variables publiques (MINTER_ROLE, totalMinted, roundOfToken, badgeOf). Tout le reste vient d'ERC721 et d'AccessControl d'OpenZeppelin 5.6.1.
  • Les fonctions de transfert héritées (transferFrom, safeTransferFrom) figurent dans l'ABI mais échouent toujours, à cause de la surcharge de _update.
  • L'événement Transfer n'est émis qu'à la frappe, avec from égal à l'adresse nulle.

Appeler le contrat avec ethers

Les exemples utilisent ethers v6 et l'adresse locale déterministe 0x5FC8d32690cc91D4c39d9d3abcBD16989F875707 (voir Blockchain locale).

Lire les badges d'un citoyen

TypeScript
import { readFileSync } from "node:fs";
import { Contract, JsonRpcProvider } from "ethers";

const abi = JSON.parse(readFileSync("backend/src/blockchain/abi/BlockLuckyPOAP.json", "utf8"));
const provider = new JsonRpcProvider("http://127.0.0.1:8545");
const poap = new Contract("0x5FC8d32690cc91D4c39d9d3abcBD16989F875707", abi, provider);

const citizen = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8";
const count: bigint = await poap.balanceOf(citizen);
const tokenId: bigint = await poap.badgeOf(1n, citizen);

if (tokenId !== 0n) {
  console.log(await poap.ownerOf(tokenId), await poap.roundOfToken(tokenId), await poap.tokenURI(tokenId));
}

badgeOf renvoie 0 quand le citoyen n'a pas de badge pour ce tour : les identifiants commencent à 1.

Lister tous les badges frappés

Le contrat n'implémente pas l'extension ERC721Enumerable. Pour lister les badges, on parcourt les identifiants de 1 à totalMinted, ou on lit les événements BadgeMinted :

TypeScript
const events = await poap.queryFilter(poap.filters.BadgeMinted(), 0, "latest");
for (const event of events) {
  const { tokenId, roundId, participant } = (event as unknown as { args: { tokenId: bigint; roundId: bigint; participant: string } }).args;
  console.log(tokenId, roundId, participant);
}

Les trois paramètres de BadgeMinted sont indexés : poap.filters.BadgeMinted(null, 3n) ne renvoie que les badges du tour 3, poap.filters.BadgeMinted(null, null, citizen) que ceux d'un citoyen.

Frapper un badge

Réservé à MINTER_ROLE. Dans le projet, seule la file d'actions on-chain le fait, avec le compte opérateur.

TypeScript
import { Wallet } from "ethers";

const minter = new Wallet(process.env.OPERATOR_PRIVATE_KEY!, provider);
const tx = await (poap.connect(minter) as Contract).mintBadge(citizen, 1n);
await tx.wait();

Un second appel identique échoue avec BadgeAlreadyMinted(1, citizen).

Vérifier les rôles

TypeScript
const MINTER_ROLE: string = await poap.MINTER_ROLE();
console.log(await poap.hasRole(MINTER_ROLE, minter.address));

Table générée

Source : smart-contract/contracts/BlockLuckyPOAP.sol. ABI : backend/src/blockchain/abi/BlockLuckyPOAP.json, vérifiée en CI par node scripts/export-abi.mjs --check.

Fonctions du contrat

Fonction Retour Mutabilité Modificateurs Rôle
badgeOf(uint256, address) uint256 variable publique - Identifiant du badge détenu par participant pour le tour roundId, ou 0 s'il n'en a pas.
mintBadge(address participant, uint256 roundId) uint256 tokenId nonpayable onlyRole(MINTER_ROLE) Frappe le badge du tour roundId pour participant et renvoie son identifiant. Un seul badge par participant et par tour. Utilise _safeMint : un contrat destinataire doit implémenter onERC721Received. Réservé à MINTER_ROLE.
MINTER_ROLE() bytes32 variable publique - Identifiant du rôle de frappe, keccak256("MINTER_ROLE"). Autorise mintBadge.
roundOfToken(uint256) uint256 variable publique - Tour de loterie auquel se rattache le badge tokenId.
setBaseUri(string baseUri) - nonpayable onlyRole(DEFAULT_ADMIN_ROLE) Change le préfixe des métadonnées pour tous les badges, existants comme futurs. Émet BaseUriUpdated. Réservé à DEFAULT_ADMIN_ROLE.
supportsInterface(bytes4 interfaceId) bool view view override(ERC721, AccessControl) ERC-165 : combine les interfaces de ERC721 (dont 0x80ac58cd) et d'AccessControl.
tokenURI(uint256 tokenId) string view view URL des métadonnées du badge : préfixe, numéro du tour, puis .json. Tous les badges d'un même tour partagent donc les mêmes métadonnées. Revert si le badge n'existe pas.
totalMinted() uint256 variable publique - Nombre de badges frappés depuis le déploiement ; c'est aussi l'identifiant du dernier badge, la numérotation commençant à 1.

Fonctions héritées

Fonction Retour Mutabilité Origine Rôle
approve(address to, uint256 tokenId) - nonpayable ERC721 ou AccessControl (OpenZeppelin) ERC-721 standard. Possible, mais sans effet utile : tout transfert est refusé.
balanceOf(address owner) uint256 view ERC721 ou AccessControl (OpenZeppelin) Nombre de badges détenus par une adresse.
DEFAULT_ADMIN_ROLE() bytes32 view AccessControl (OpenZeppelin) Rôle administrateur, administrateur de MINTER_ROLE.
getApproved(uint256 tokenId) address view ERC721 ou AccessControl (OpenZeppelin) Adresse approuvée pour un badge.
getRoleAdmin(bytes32 role) bytes32 view AccessControl (OpenZeppelin) Rôle qui administre le rôle donné.
grantRole(bytes32 role, address account) - nonpayable AccessControl (OpenZeppelin) Accorde un rôle. Réservé à l'administrateur du rôle.
hasRole(bytes32 role, address account) bool view AccessControl (OpenZeppelin) Indique si un compte détient un rôle.
isApprovedForAll(address owner, address operator) bool view ERC721 ou AccessControl (OpenZeppelin) Indique si un opérateur est approuvé pour tous les badges d'un détenteur.
name() string view ERC721 ou AccessControl (OpenZeppelin) Nom de la collection : BlockLucky EtherBay POAP.
ownerOf(uint256 tokenId) address view ERC721 ou AccessControl (OpenZeppelin) Détenteur d'un badge. Revert si le badge n'existe pas.
renounceRole(bytes32 role, address callerConfirmation) - nonpayable AccessControl (OpenZeppelin) Permet à un compte de renoncer à son propre rôle.
revokeRole(bytes32 role, address account) - nonpayable AccessControl (OpenZeppelin) Retire un rôle. Réservé à l'administrateur du rôle.
safeTransferFrom(address from, address to, uint256 tokenId) - nonpayable ERC721 ou AccessControl (OpenZeppelin) ERC-721 standard, toujours refusé : SoulboundToken, ou ERC721InvalidReceiver vers l'adresse nulle.
safeTransferFrom(address from, address to, uint256 tokenId, bytes data) - nonpayable ERC721 ou AccessControl (OpenZeppelin) ERC-721 standard, toujours refusé : SoulboundToken, ou ERC721InvalidReceiver vers l'adresse nulle.
setApprovalForAll(address operator, bool approved) - nonpayable ERC721 ou AccessControl (OpenZeppelin) ERC-721 standard. Possible, mais sans effet utile : tout transfert est refusé.
symbol() string view ERC721 ou AccessControl (OpenZeppelin) Symbole de la collection : BLPOAP.
transferFrom(address from, address to, uint256 tokenId) - nonpayable ERC721 ou AccessControl (OpenZeppelin) ERC-721 standard, toujours refusé : SoulboundToken, ou ERC721InvalidReceiver vers l'adresse nulle.

Événements

Événement Paramètres Rôle
Approval address indexed owner, address indexed approved, uint256 indexed tokenId hérité (ERC721, approbation d'un badge)
ApprovalForAll address indexed owner, address indexed operator, bool approved hérité (ERC721, approbation d'un opérateur)
BadgeMinted uint256 indexed tokenId, uint256 indexed roundId, address indexed participant Émis par mintBadge avec l'identifiant du badge, le tour et le participant.
BaseUriUpdated string baseUri Émis par setBaseUri avec le nouveau préfixe des métadonnées.
RoleAdminChanged bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole hérité (AccessControl, administrateur d'un rôle modifié)
RoleGranted bytes32 indexed role, address indexed account, address indexed sender hérité (AccessControl, rôle accordé)
RoleRevoked bytes32 indexed role, address indexed account, address indexed sender hérité (AccessControl, rôle retiré)
Transfer address indexed from, address indexed to, uint256 indexed tokenId hérité (ERC721, émis uniquement à la frappe, depuis l'adresse nulle)

Erreurs

Erreur Paramètres Déclenchée quand
AccessControlBadConfirmation - héritée (AccessControl, renounceRole appelé pour un autre compte)
AccessControlUnauthorizedAccount address account, bytes32 neededRole héritée (AccessControl, l'appelant n'a pas le rôle exigé)
BadgeAlreadyMinted uint256 roundId, address participant mintBadge est appelé pour un participant qui a déjà le badge de ce tour.
ERC721IncorrectOwner address sender, uint256 tokenId, address owner héritée (ERC721, propriétaire incorrect)
ERC721InsufficientApproval address operator, uint256 tokenId héritée (ERC721, approbation insuffisante)
ERC721InvalidApprover address approver héritée (ERC721, approbateur invalide)
ERC721InvalidOperator address operator héritée (ERC721, opérateur invalide)
ERC721InvalidOwner address owner héritée (ERC721, adresse nulle passée à balanceOf)
ERC721InvalidReceiver address receiver héritée (ERC721, destinataire nul ou contrat sans onERC721Received à la frappe)
ERC721InvalidSender address sender héritée (ERC721, émetteur invalide)
ERC721NonexistentToken uint256 tokenId héritée (ERC721, badge inexistant dans ownerOf ou tokenURI)
SoulboundToken uint256 tokenId Un transfert de badge est tenté entre deux adresses non nulles, par transferFrom ou safeTransferFrom, quel que soit l'appelant.
ZeroAddressNotAllowed - L'adresse nulle est passée comme administrateur au constructeur ou comme participant à mintBadge.