This section introduces the basic concepts of Canvas badges. For jumping into code examples, see Badge Examples.
- What is a badge?
- How to implement a new badge?
- Badge Token URI
- Ways to Issue Badges
- Overview of Requirements
- Upgradable Badges
- Extensions
- Examples
- Troubleshooting
Each Canvas badge is an EAS attestation, with some additional logic attached to it.
The badge attestation uses the official Scroll Canvas schema (see BADGE_SCHEMA
in Deployments).
This means that the badge data contains two fields: address badge, bytes payload
, and badges are issued through the official Canvas badge resolver contract.
Each badge must implement a certain interface to ensure it is compatible with Canvas.
In particular, each badge must implement 3 APIs (see IScrollBadge
):
issueBadge
: Implement arbitrary logic that is triggered when a new badge is created.revokeBadge
: Implement arbitrary logic that is triggered when a badge is revoked.badgeTokenURI
: Return the badge token URI. This follows the same schema as ERC721'stokenURI
. In most cases, the badge contract would use a static image, shared by all instances of this badge. However, on-chain-generated SVG data URLs are also possible.
As a badge developer, it is strongly recommended that your contract inherits from ScrollBadge
.
Additionally, you can use one or more extensions.
Refer to the examples in examples.
While this is not mandatory, we recommend creating badges that do no expire, are non-revocable, and are singletons (at most 1 badge per user).
Each badge must define a badge token URI.
The badge token URI is very similar to the tokenURI in ERC-721.
It must point to a metadata JSON object that contains name
, description
, image
, and issuerName
.
You can use a normal URL, an IPFS link, or a data URL as your token URI.
The metadata is used by the Canvas frontend to render the badge.
For example, the badge token URI https://nft.scroll.io/canvas/year/2024.json points to the following metadata:
{
"name": "Ethereum Year",
"description": "Check out the Ethereum Year Badge! It's like a digital trophy that shows off the year your wallet made its debut on Ethereum. It's a little present from Scroll to celebrate all the cool stuff you've done in the Ethereum ecosystem.",
"image": "https://nft.scroll.io/canvas/year/2024.webp",
"issuerName": "Scroll"
}
Your badge contract can provide a single URI for all badges, in which case all instances of your badge will look the same.
Alternatively, you can also render a different image for different instances of your badge, see EthereumYearBadge
.
You should also configure a default badge token URI, see ScrollBadgeDefaultURI
.
Design guidelines for badge images:
- Maximum resolution: 480px x 480px
- Optimal resolution: 600px x 600px
- File size: Under 300KB
Badges are created by attesting to the recipient using the BADGE_SCHEMA
.
EAS provides multiple interfaces to attest: attest
, attestByDelegation
, multiAttest
, multiAttestByDelegation
. See IEAS.sol
.
There are three main badge types of badges:
-
Permissionless. Permissionless badges allow users to attest to themselves using
EAS.attest
. The badge contract ensures that the user is authorized to mint. SeeScrollBadgePermissionless.sol
andScrollBadgeTokenOwner.sol
. -
Backend-authorized. For backend-authorized badges, the issuer maintains a centralized backend service. This backend implements some off-chain eligibility check and exposes an eligibility check and claim API. If the user is authorized to mint, the backend issues a signed permit. The user then mints using this permit.
See this document for the API requirements.
For backend-authorized badges, you need to deploy two contracts: the badge contract, and an
AttesterProxy
.AttesterProxy
allows executing delegated attestations in arbitrary order. The user can mint the badge by callingAttesterProxy.attestByDelegation
and providing the signed permit. -
Gifted. Badges can also be issued with no user interaction. To do this, the issuer uses
EAS.attest
orEAS.multiAttest
to airdrop these badges to a list of users.
Type | Description | Requirements | Required Extensions | Examples |
---|---|---|---|---|
|
Badge checks eligibility based on smart contract. Example: Badges attesting to completing an onchain transaction or holding an NFT are eligible to mint the badge. |
Basic Requirements:
Additional Requirements:
|
|
|
|
Badge checks eligibility based on the issuer’s API. Example: Badges attesting to completing offchain actions or a certain allow list. |
All Basic Requirements, plus
|
||
|
Badge checks eligibility based on the issuer’s API and automatically sends to users' canvas. There is no minting required for users to display the badge. Example: Badges attesting to ownership or paid membership on other platforms / chains. |
All Basic Requirements, plus
|
This section is not about contract upgradability. If you want to make your badge contract upgradable, use any standard upgradability pattern.
Upgradable badges are badges that can evolve over time. This pattern is most suitable for badges that represent that the user has reached a certain "level". A user can first mint a badge at a certain level. Then, once the user is eligible, they can upgrade their badge to a higher level.
Upgradable badges must implement the IScrollBadgeUpgradeable
interface.
Currently this interface only supports on-chain upgrade conditions.
This repo contains some useful extensions:
ScrollBadgeAccessControl
restricts who can create and revoke this badge.ScrollBadgeCustomPayload
adds custom payload support to the badge.ScrollBadgeDefaultURI
sets a default badge token URI.ScrollBadgeEligibilityCheck
adds a standard on-chain eligibility check interface.ScrollBadgeNoExpiry
disables expiration for the badge.ScrollBadgeNonRevocable
disables revocation for the badge.ScrollBadgeSBT
attaches an SBT token to each badge attestation.ScrollBadgeSelfAttest
ensures that only the recipient of the badge can create the badge.ScrollBadgeSingleton
ensures that each user can only have at most one of the badge.
This repo also contains some examples:
ScrollBadgeSimple
is a simple badge with fixed metadata.ScrollBadgePermissionless
is a permissionless badge that anyone can mint to themselves.ScrollBadgeLevels
is an SBT badge that stores a level in its payload and renders different images based on this level.ScrollBadgeTokenOwner
is a badge that is tied to the ownership of a Scroll Origins NFT.
We recommend going through the requirements before your badge is published.
Once your badge has been deployed on Scroll, you can auto-check some of these requirements by running yarn check-badge
.
If your badge minting transaction reverts, we recommend debugging using cast
:
cast run --rpc-url https://rpc.scroll.io [txhash]
This call will simulate the transaction in a local environment and show you the call stack and revert reason.