Skip to main content
Sigvex

Royalty Bypass Remediation

Query and enforce ERC-2981 royalty payments inside marketplace sale logic so creator revenue cannot be circumvented.

Royalty Bypass Remediation

Overview

ERC-2981 royalties are advisory. The standard exposes a royaltyInfo function but never enforces payment, so a marketplace that completes a sale without querying and paying the royalty silently strips creators of revenue. The fix is to make royalty enforcement part of every settlement path that moves an NFT in exchange for value.

Related Detector: Royalty Bypass

Before (Vulnerable)

function executeSale(uint256 tokenId, uint256 price) external payable {
    require(msg.value >= price);
    nft.transferFrom(seller, msg.sender, tokenId);
    payable(seller).transfer(price); // No royalty paid
}

After (Fixed)

function executeSale(uint256 tokenId, uint256 price) external payable {
    require(msg.value >= price);
    (address receiver, uint256 royalty) =
        IERC2981(address(nft)).royaltyInfo(tokenId, price);
    require(royalty <= price, "Royalty exceeds price");
    nft.transferFrom(seller, msg.sender, tokenId);
    if (royalty > 0 && receiver != address(0)) {
        payable(receiver).transfer(royalty);
    }
    payable(seller).transfer(price - royalty);
}

The fixed version queries royaltyInfo before settling, caps the royalty at the sale price, and pays the receiver before remitting the remainder to the seller. Because enforcement lives inside the only function that transfers the token, no settlement path can skip it.

Alternative Mitigations

  • Use transfer-hook or allowlist token standards (such as ERC-721C-style transfer validators) that block transfers routed through marketplaces which do not honor royalties. This shifts enforcement to the token itself rather than relying on every marketplace.
  • Detect ERC-2981 support with supportsInterface(0x2a55205a) before settling, and fall back to a default policy for tokens that do not implement it.
  • Route all settlement through a single audited settlement contract so royalty logic is defined once instead of duplicated per listing type.

Common Mistakes

  • Querying royaltyInfo for logging or display but never sending the funds — the detector flags exactly this gap.
  • Subtracting the royalty from the seller payout without actually transferring it to the receiver, which under-pays the seller and pays no one.
  • Assuming peer-to-peer transferFrom calls outside the marketplace can be policed by marketplace code. They cannot; only token-level transfer restrictions cover that path.
  • Hardcoding a fixed royalty percentage instead of reading the per-token value the standard returns.

References