Mapa completo de controle de acesso dos cinco contratos do ecossistema BitChicken.
Fonte de verdade: os próprios contratos em RW.BC.Crypto/contracts/.
bitchicken-token.sol)Usa AccessControlUpgradeable do OpenZeppelin — sem hierarquia de Ownable, apenas roles.
| Constante | Valor (keccak256) |
Quem recebe no deploy |
|---|---|---|
DEFAULT_ADMIN_ROLE |
0x00 (padrão OZ) |
admin passado no initialize (deployer → transferido para ADMIN_WALLET no script) |
MINTER_ROLE |
keccak256("MINTER_ROLE") |
No deploy inicial: deployer (revogado logo após); depois: BitChickenStaking (yield) |
PAUSER_ROLE |
keccak256("PAUSER_ROLE") |
pauser passado no initialize (mesmo que admin no script de deploy) |
Atenção: o BitChickenNFT usa burnFrom (não mint) para queimar BCKN no rename — ele não
precisa de MINTER_ROLE. O Forge acumula recompensas de referral em BNB (não em BCKN), então
também não recebe MINTER_ROLE. Apenas o Staking recebe MINTER_ROLE para emitir yield.
| Função | Role exigida | Efeito |
|---|---|---|
mint(address, uint256) |
MINTER_ROLE |
Emite tokens até o emissionCap; reverte EmissionCapExceeded se exceder |
setEmissionCap(uint256) |
DEFAULT_ADMIN_ROLE |
Atualiza o cap global (nunca abaixo do totalMinted) |
pause() |
PAUSER_ROLE |
Para todas as transferências |
unpause() |
PAUSER_ROLE |
Retoma transferências |
grantRole / revokeRole |
DEFAULT_ADMIN_ROLE (do role alvo) |
Gerência de roles (padrão OZ AccessControl) |
bitchicken-nft.sol)Usa Ownable2StepUpgradeable: transferência de ownership requer dois passos (transferOwnership
pelo owner atual + acceptOwnership pelo pendente), eliminando risco de perda por erro de endereço.
No script deploy.ts, o deployer inicia nft.transferOwnership(ADMIN_WALLET). O ADMIN_WALLET
deve chamar acceptOwnership() para finalizar. Até isso ocorrer, o deployer ainda é o owner.
forgeMintforgeMint não usa onlyOwner — usa verificação explícita de endereço:
if (msg.sender != $.forge) revert CallerNotForge();
O endereço autorizado é configurado via setForge(forge_) (que exige onlyOwner). Somente o
contrato BitChickenForge deployado pode chamar forgeMint.
onlyOwner| Função | Efeito |
|---|---|
setForge(address) |
Define o endereço do Forge autorizado a chamar forgeMint |
setRenamePrice(uint256) |
Preço em BCKN para renomear um token (0 = grátis) |
setRoyalty(address, uint96) |
Configura royalty EIP-2981 padrão (destinatário + bps) |
registerEdition(...) |
Registra uma nova edição no catálogo (stats + supply + janela + pesos) |
setEditionActive(uint256, bool) |
Ativa ou desativa uma edição para o gacha |
setEditionWindow(uint256, uint64, uint64) |
Atualiza janela temporal de mint de uma edição |
updateTierPrices(uint256[10]) |
Substitui a tabela de 10 preços de tier (BNB wei, estritamente crescentes) |
setReferralLevels(uint256[], uint16[]) |
Substitui a tabela de níveis do programa de indicação |
pause() / unpause() |
Para / retoma mints e transferências |
withdraw() |
Drena o saldo BNB do contrato NFT para o owner (válvula de segurança) |
| Função | Notas |
|---|---|
registerReferrer() |
Qualquer endereço pode se registrar como referenciador (código único, permanente) |
rename(uint256, string) |
Somente o dono do token pode renomear (verificação: ownerOf(tokenId) != msg.sender) |
bitchicken-forge.sol)Contrato não-upgradeável. Herda de VRFConsumerBaseV2Plus, que por sua vez herda de
ConfirmedOwner. O mecanismo de ownership é o ConfirmedOwner do Chainlink (padrão similar ao
Ownable do OZ, mas específico da Chainlink).
No construtor, o owner_ é passado explicitamente. Se owner_ != msg.sender, é chamado
transferOwnership(owner_). No script de deploy, owner_ = ADMIN_WALLET.
onlyOwner| Função | Efeito |
|---|---|
setVRFConfig(bytes32, uint256, uint32, uint16) |
Atualiza keyHash, subId, callbackGasLimit, requestConfirmations |
withdraw() |
Drena o saldo BNB do Forge para o owner, preservando escrow de refunds e referrals |
fulfillRandomWords — apenas VRF coordinatorfulfillRandomWords é internal override herdado de VRFConsumerBaseV2Plus. O contrato base
garante que apenas o s_vrfCoordinator (definido no construtor) pode acionar o callback. Qualquer
chamada externa direta é impossível — a função não é external.
| Função | Notas |
|---|---|
requestObtain(uint8, uint256, string) payable |
Qualquer endereço pode solicitar um ovo |
cancelStaleRequest(uint256) |
Somente o comprador original pode cancelar (verificação: req.buyer != msg.sender) |
claimRefund() |
Qualquer endereço pode sacar seu próprio saldo de reembolso |
claimReferralBnb() |
Qualquer endereço pode sacar seu próprio saldo de referral |
bitchicken-staking.sol)Usa Ownable2StepUpgradeable (mesma proteção de dois passos do NFT).
onlyOwner| Função | Efeito |
|---|---|
setBaseRate(uint256) |
Taxa base de yield (deve ser <= MAX_BASE_RATE) |
setWeights(uint256, uint256, uint256) |
Pesos de health, skill e morale no cálculo de yield |
setClaimBurnBps(uint256) |
Taxa de retenção no claim (bps, 0-10000; o montante retido não é mintado) |
setIdealPairMultiplierBps(uint256) |
Multiplicador de yield para casais do mesmo edition (>= 10000) |
pause() / unpause() |
Para / retoma stake, claim e unstake |
| Função | Notas |
|---|---|
stakePair(uint256, uint256) |
Qualquer endereço pode fazer staking de par que ele mesmo possua |
claim(uint256) / claimRange(uint256, uint256) |
Somente o dono do par pode fazer claim (verificação: p.owner != staker) |
unstakePair(uint256) |
Somente o dono do par pode desfazer o staking |
bitchicken-marketplace.sol)Usa Ownable2StepUpgradeable.
onlyOwner| Função | Efeito |
|---|---|
setPlatformFee(address, uint256) |
Atualiza o destinatário (feeSink) e a taxa da plataforma (bps) |
pause() / unpause() |
Para / retoma listagens e compras |
| Função | Notas |
|---|---|
list(uint256, uint96) |
Somente o dono do token pode listar (verificação: nft.ownerOf(tokenId) != msg.sender) |
cancel(uint256) |
Somente o seller original pode cancelar (verificação: l.seller != msg.sender) |
obtain(uint256) payable |
Qualquer endereço pode comprar um NFT listado |
proposeSwap(uint256, uint256) payable |
Somente o dono do token oferecido pode propor |
cancelSwap(uint256) |
Somente o proposer original pode cancelar |
acceptSwap(uint256) |
Somente o dono do token desejado pode aceitar |
| Contrato | Função administrativa | Quem pode chamar |
|---|---|---|
| BitChickenToken | mint |
MINTER_ROLE (Staking) |
| BitChickenToken | setEmissionCap |
DEFAULT_ADMIN_ROLE (ADMIN_WALLET) |
| BitChickenToken | pause / unpause |
PAUSER_ROLE (ADMIN_WALLET) |
| BitChickenNFT | setForge |
owner (ADMIN_WALLET) |
| BitChickenNFT | registerEdition / setEditionActive / setEditionWindow |
owner (ADMIN_WALLET) |
| BitChickenNFT | updateTierPrices / setReferralLevels / setRenamePrice / setRoyalty |
owner (ADMIN_WALLET) |
| BitChickenNFT | pause / unpause / withdraw |
owner (ADMIN_WALLET) |
| BitChickenNFT | forgeMint |
somente endereço $.forge (BitChickenForge) |
| BitChickenForge | setVRFConfig / withdraw |
owner (ADMIN_WALLET, via ConfirmedOwner) |
| BitChickenForge | fulfillRandomWords |
somente VRF coordinator (internal, não acessível externamente) |
| BitChickenStaking | setBaseRate / setWeights / setClaimBurnBps / setIdealPairMultiplierBps |
owner (ADMIN_WALLET) |
| BitChickenStaking | pause / unpause |
owner (ADMIN_WALLET) |
| BitChickenMarketplace | setPlatformFee |
owner (ADMIN_WALLET) |
| BitChickenMarketplace | pause / unpause |
owner (ADMIN_WALLET) |
Fase de desenvolvimento (atual): o owner de todos os contratos é uma EOA (ADMIN_WALLET,
configurada via .env em scripts/deploy.ts). Esse modelo é adequado para a fase de dev mas não é
recomendado para mainnet por expor o ecossistema a um único ponto de falha.
Futuro (mainnet): o owner dos proxies e do Forge deve ser substituído por um Gnosis Safe (multisig) com um TimelockController interposto. Isso exige que qualquer função administrativa seja proposta no Safe, aprovada por N/M signatários, aguarde o delay do Timelock e então execute. O procedimento de upgrade já documenta esse requisito em upgrade-procedure.md (seção “Pós-desenvolvimento”).
A possibilidade de fazer esse upgrade sem quebrar estado é garantida pelo padrão de proxy transparente e pelo storage namespaced ERC-7201 — a troca de owner/multisig não requer redeploy dos proxies.