Skip to content

Commit

Permalink
badge WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
sebsadface committed Oct 5, 2024
1 parent 6acb0db commit 6104913
Show file tree
Hide file tree
Showing 10 changed files with 1,260 additions and 8 deletions.
22 changes: 22 additions & 0 deletions contracts/interfaces/story-nft/IERC5192.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

/// @title Minimal Soulbound NFT Interface
/// @notice Minimal interface for soulbinding EIP-721 NFTs
interface IERC5192 {
/// @notice Emitted when the locking status is changed to locked.
/// @dev If a token is minted and the status is locked, this event should be emitted.
/// @param tokenId The identifier for a token.
event Locked(uint256 tokenId);

/// @notice Emitted when the locking status is changed to unlocked.
/// @dev If a token is minted and the status is unlocked, this event should be emitted.
/// @param tokenId The identifier for a token.
event Unlocked(uint256 tokenId);

/// @notice Returns the locking status of an Soulbound Token
/// @dev SBTs assigned to zero address are considered invalid, and queries
/// about them do throw.
/// @param tokenId The identifier for an SBT.
function locked(uint256 tokenId) external view returns (bool);
}
67 changes: 67 additions & 0 deletions contracts/interfaces/story-nft/IOrgNFT.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";

/// @title Organization NFT Interface
/// @notice Each organization token represents a Story ecosystem project.
/// The root organization token represents Story.
/// Each organization token register as a IP on Story and is a derivative of the root organization IP.
interface IOrgNFT is IERC721Metadata {
////////////////////////////////////////////////////////////////////////////
// Errors //
////////////////////////////////////////////////////////////////////////////
/// @notice Caller is not the StoryNFTFactory contract.
/// @param caller The address of the caller.
/// @param storyNftFactory The address of the `StoryNFTFactory` contract.
error OrgNFT__CallerNotStoryNFTFactory(address caller, address storyNftFactory);

/// @notice Root organization NFT has already been minted.
error OrgNFT__RootOrgNftAlreadyMinted();

/// @notice Root organization NFT has not been minted yet (`mintRootOrgNft` has not been called).
error OrgNFT__RootOrgNftNotMinted();

/// @notice Zero address provided as a param to OrgNFT functions.
error OrgNFT__ZeroAddressParam();

////////////////////////////////////////////////////////////////////////////
// Events //
////////////////////////////////////////////////////////////////////////////
/// @notice Emitted when a organization token minted.
/// @param recipient The address of the recipient of the organization token.
/// @param orgNft The address of the organization NFT.
/// @param tokenId The ID of the minted organization token.
/// @param orgIpId The ID of the organization IP.
event OrgNFTMinted(address recipient, address orgNft, uint256 tokenId, address orgIpId);

////////////////////////////////////////////////////////////////////////////
// Functions //
////////////////////////////////////////////////////////////////////////////
/// @notice Mints the root organization token and register it as an IP.
/// @param recipient The address of the recipient of the root organization token.
/// @param tokenURI The URI of the root organization token.
/// @return rootOrgTokenId The ID of the root organization token.
/// @return rootOrgIpId The ID of the root organization IP.
function mintRootOrgNft(
address recipient,
string memory tokenURI
) external returns (uint256 rootOrgTokenId, address rootOrgIpId);

/// @notice Mints a organization token, register it as an IP,
/// and makes the IP as a derivative of the root organization IP.
/// @param recipient The address of the recipient of the minted organization token.
/// @param tokenURI The URI of the minted organization token.
/// @return orgTokenId The ID of the minted organization token.
/// @return orgIpId The ID of the organization IP.
function mintOrgNft(
address recipient,
string memory tokenURI
) external returns (uint256 orgTokenId, address orgIpId);

/// @notice Returns the ID of the root organization IP.
function getRootOrgIpId() external view returns (address);

/// @notice Returns the total supply of OrgNFT.
function totalSupply() external view returns (uint256);
}
75 changes: 75 additions & 0 deletions contracts/interfaces/story-nft/IStoryBadgeNFT.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";

import { IERC5192 } from "./IERC5192.sol";

/// @title Story Badge NFT Interface
/// @notice A Story Badge NFT is a soulbound NFT that has an unified token URI for all tokens.
interface IStoryBadgeNFT is IERC5192, IERC721Metadata {
////////////////////////////////////////////////////////////////////////////
// Errors //
////////////////////////////////////////////////////////////////////////////
/// @notice Invalid whitelist signature.
error StoryBadgeNFT__InvalidSignature();

/// @notice The provided whitelist signature is already used.
error StoryBadgeNFT__SignatureAlreadyUsed();

/// @notice Badges are soulbound, cannot be transferred.
error StoryBadgeNFT__TransferLocked();

/// @notice Zero address provided as a param to StoryBadgeNFT functions.
error StoryBadgeNFT__ZeroAddressParam();

////////////////////////////////////////////////////////////////////////////
// Structs //
////////////////////////////////////////////////////////////////////////////
/// @notice Struct for initializing the StoryBadgeNFT contract.
/// @param name The name of the collection.
/// @param symbol The symbol of the collection.
/// @param contractURI The contract URI of the collection (follows OpenSea contract-level metadata standard).
/// @param tokenURI The token URI for all the badges (follows OpenSea metadata standard).
/// @param signer The signer of the whitelist signatures.
struct InitParams {
string name;
string symbol;
string contractURI;
string tokenURI;
address signer;
}

////////////////////////////////////////////////////////////////////////////
// Events //
////////////////////////////////////////////////////////////////////////////
/// @notice Emitted when a badge NFT is minted.
/// @param recipient The address of the recipient of the badge NFT.
/// @param tokenId The token ID of the minted badge NFT.
/// @param ipId The ID of the badge NFT IP.
event StoryBadgeNFTMinted(address recipient, uint256 tokenId, address ipId);

/// @notice Emitted when the signer is updated.
/// @param signer The new signer address.
event StoryBadgeNFTSignerUpdated(address signer);

////////////////////////////////////////////////////////////////////////////
// Functions //
////////////////////////////////////////////////////////////////////////////
/// @notice Mints a badge for the given recipient, registers it as an IP,
/// and makes it a derivative of the organization IP.
/// @param recipient The address of the recipient of the badge NFT.
/// @param signature The signature from the whitelist signer. This signautre is genreated by having the whitelist
/// signer sign the caller's address (msg.sender) for this `mint` function.
/// @return tokenId The token ID of the minted badge NFT.
/// @return ipId The ID of the badge NFT IP.
function mint(address recipient, bytes calldata signature) external returns (uint256 tokenId, address ipId);

/// @notice Updates the whitelist signer.
/// @param signer_ The new whitelist signer address.
function setSigner(address signer_) external;

/// @notice Updates the unified token URI for all badges.
/// @param tokenURI_ The new token URI.
function setTokenURI(string memory tokenURI_) external;
}
124 changes: 124 additions & 0 deletions contracts/interfaces/story-nft/IStoryNFTFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

/// @title Story NFT Factory Interface
/// @notice Story NFT Factory is the entrypoint for creating new Story NFT collections.
interface IStoryNFTFactory {
////////////////////////////////////////////////////////////////////////////
// Errors //
////////////////////////////////////////////////////////////////////////////
/// @notice Invalid signature provided to StoryNFTFactory functions.
/// @param signature The signature that is invalid.
error StoryNFTFactory__InvalidSignature(bytes signature);

/// @notice NftTemplate is not whitelisted to be used as a StoryNFT.
/// @param nftTemplate The NFT template that is not whitelisted.
error StoryNFTFactory__NftTemplateNotWhitelisted(address nftTemplate);

/// @notice Organization is already deployed by the StoryNFTFactory.
/// @param orgName The name of the organization that is already deployed.
/// @param deployedStoryNft The address of the already deployed StoryNFT for the organization.
error StoryNFTFactory__OrgAlreadyDeployed(string orgName, address deployedStoryNft);

/// @notice Organization is not found in the StoryNFTFactory.
/// @param orgName The name of the organization that is not found.
error StoryNFTFactory__OrgNotFound(string orgName);

/// @notice Signature is already used to deploy a StoryNFT.
/// @param signature The signature that is already used.
error StoryNFTFactory__SignatureAlreadyUsed(bytes signature);

/// @notice BaseStoryNFT is not supported by the StoryNFTFactory.
/// @param tokenContract The address of the token contract that does not implement BaseStoryNFT.
error StoryNFTFactory__UnsupportedBaseStoryNFT(address tokenContract);

/// @notice Zero address provided as a param to StoryNFTFactory functions.
error StoryNFTFactory__ZeroAddressParam();

////////////////////////////////////////////////////////////////////////////
// Events //
////////////////////////////////////////////////////////////////////////////
/// @notice Emitted when the default StoryNFT template is updated.
/// @param defaultStoryNftTemplate The new default StoryNFT template.
event StoryNFTFactoryDefaultStoryNftTemplateUpdated(address defaultStoryNftTemplate);

/// @notice Emitted when a new orgnization NFT is minted and a new StoryNFT associated with it is deployed.
/// @param orgName The name of the organization.
/// @param orgNft The address of the organization NFT.
/// @param orgTokenId The token ID of the organization NFT.
/// @param orgIpId The ID of the organization IP.
/// @param storyNft The address of the deployed StoryNFT.
event StoryNftDeployed(string orgName, address orgNft, uint256 orgTokenId, address orgIpId, address storyNft);

/// @notice Emitted when the signer of the StoryNFTFactory is updated.
/// @param signer The new signer of the StoryNFTFactory.
event StoryNFTFactorySignerUpdated(address signer);

/// @notice Emitted when a new Story NFT template is whitelisted.
/// @param nftTemplate The new Story NFT template that is whitelisted to be used in StoryNFTFactory.
event StoryNFTFactoryNftTemplateWhitelisted(address nftTemplate);

////////////////////////////////////////////////////////////////////////////
// Functions //
////////////////////////////////////////////////////////////////////////////
/// @notice Mints a new organization NFT and deploys (creates a clone of) `storyNftTemplate` as the StoryNFT
/// associated with the new organization NFT.
/// @param storyNftTemplate The address of a whitelisted StoryNFT template to be cloned.
/// @param storyNftOwner The address of the owner of the new StoryNFT contract.
/// @param orgName The name of the organization.
/// @param orgTokenURI The token URI of the organization NFT.
/// @param signature The signature from the StoryNFTFactory's whitelist signer. This signautre is genreated by
/// having the whitelist signer sign the caller's address (msg.sender) for this `deployStoryNft` function.
/// @param initData The initialization data for the StoryNFT (see {IStoryBadgeNFT-InitParams} for an example).
/// @return orgTokenId The token ID of the organization NFT.
/// @return orgIpId The ID of the organization IP.
/// @return storyNft The address of the dployed StoryNFT
function deployStoryNft(
address storyNftTemplate,
address storyNftOwner,
string calldata orgName,
string calldata orgTokenURI,
bytes calldata signature,
bytes calldata initData
) external returns (uint256 orgTokenId, address orgIpId, address storyNft);

/// @notice Mints a new organization NFT and deploys (creates a clone of) `storyNftTemplate` as the StoryNFT
/// associated with the new organization NFT.
/// @dev Enforced to be only callable by the protocol admin in governance.
/// @param storyNftTemplate The address of a whitelisted StoryNFT template to be cloned.
/// @param storyNftOwner The address of the owner of the new StoryNFT contract.
/// @param orgName The name of the organization.
/// @param orgTokenURI The token URI of the organization NFT.
/// @param initData The initialization data for the StoryNFT (see {IStoryBadgeNFT-InitParams} for an example).
/// @param isRootOrg Whether the organization is the root organization.
/// @return orgTokenId The token ID of the organization NFT.
/// @return orgIpId The ID of the organization IP.
/// @return storyNft The address of the dployed StoryNFT
function deployStoryNftByAdmin(
address storyNftTemplate,
address storyNftOwner,
string calldata orgName,
string calldata orgTokenURI,
bytes calldata initData,
bool isRootOrg
) external returns (uint256 orgTokenId, address orgIpId, address storyNft);

/// @notice Sets the default StoryNFT template of the StoryNFTFactory.
/// @param defaultStoryNftTemplate The new default StoryNFT template.
function setDefaultStoryNftTemplate(address defaultStoryNftTemplate) external;

/// @notice Sets the signer of the StoryNFTFactory.
/// @param signer The new signer of the StoryNFTFactory.
function setSigner(address signer) external;

/// @notice Whitelists a new StoryNFT template.
/// @param storyNftTemplate The new StoryNFT template to be whitelisted.
function whitelistNftTemplate(address storyNftTemplate) external;

/// @notice Returns the default StoryNFT template address.
function getDefaultStoryNftTemplate() external view returns (address);

/// @notice Returns the address of the StoryNFT for a given organization name.
/// @param orgName The name of the organization.
function getStoryNftAddress(string calldata orgName) external view returns (address);
}
Loading

0 comments on commit 6104913

Please sign in to comment.