A significant revision is coming soon…
Please visit here for the on-going modification:
Abstract
SCC0 (Smart Creative Commons Zero) is the first public goods license tailored for public decentralized applications (Smart Commons), including dApps, dAIpps(AIs). Being public goods, Smart Commons are open source and free for anyone to use (except for gas fees).
This standard introduces a structured way for smart contracts to declare SCC0 compliance, enabling automated on-chain verification and governance integration.
Two versions of SCC0 have been deployed by DAism, and anyone can deploy additional versions to further expand its applications. The declaration of any dApp/dAIpp is as simple as:
address public constant LICENSE = contract_address;
Motivation
To ensure that dApps and dAIpps can transparently declare their compliance with SCC0, we propose a standardized way to embed license-related variables in smart contracts. This allows for:
- On-chain verification of SCC0 adherence.
- Automated interaction checks between contracts.
- A reward mechanism that enables a specific public governance fund to distribute anonymous rewards to contributors.
Specification
This section outlines the technical specifications for implementing the Smart Creative Commons Zero (SCC0) license for public decentralized applications (dApps/dAIpps). It defines a standardized on-chain framework that allows smart contracts to declare SCC0 compliance, supports automated verification, and facilitates decentralized governance.
1. SCC0 License Declaration
Since V2, every smart contract that intends to operate as a Smart Common under the SCC0 license must declare its license by including a constant variable referencing the relevant SCC0 Compliance Contract. For example:
SCC0 v2 Declaration (recommended for extended interactions)
- SCC0 v2 extends the original standard and requires the following declarations in your dApp/dAIpp:
address public constant LICENSE = 0xaCb910db73473944B2D23D37A0e46F57a43c6a49;
// Recommended declarations for better interaction:
address public owner; // Address for rewards
string public scName; // Smart Common name
string public scType; // Smart Common type
Declaring the LICENSE
constant ensures that any interactions with the smart contract can be automatically verified against the SCC0 standard.
For any upgradeable dApp/dAIpp , we strongly recommend to set owner with a multi-sig address, so as to pass the control to some dAIpps (AIs) in the future.
SCC0 v1
SCC0 v1 doesn’t have a declaration. You have to read the lists in a specific smart contract of DAism.
2. Compliance Contracts of v1 and v2
SCC0 v1 Compliance Contract
SCC0 v1 has been deployed by DAism, and any dApp/dAIpp adhering to it must:
-
Interact with DAism’s smart contract
0xdFBF69B7E5366FB3001C9a214dd85c5FE3f90bAe
. Or go to DAism to mint a smart common. -
SCC0 v1 Compliance Contract which is deployed by DAism:
contract SCC0License {
string public constant LICENSENAME = "SCC0";
uint8 public constant VERSION = 1;
bool public constant SELFISSUEDTOKEN = false;
bool public constant NORIGHTSEXCEPTREWARDS = true;
bool public constant NOLIABILITY = true;
bool public constant ANONYMITYENSURED = true;
bool public constant OPEN_SOURCE = true;
bool public constant PERMANENTLY_FREE = true;
address public constant GOVERNANCE = 0xe40b05570d2760102c59bf4ffc9b47f921b67a1F;
}
- DAism has defined the Smart Common structure:
struct SCInfo {
string name; // Name of the smart common
string symbol; // Symbol of the smart common
string desc; // Description of the smart common
address manager; // Address of the smart common manager
uint16 version; // Version number of the smart common
string SCType; // Type of the smart common
}
- Additional mappings and governance structures are included for community interactions:
mapping(address => Object.Member) public memberInfos; // Stores Smart Common members and their dividend ratios
uint32 public proposalLifetime; // Validity period of Smart Common proposals
uint32 public proposalCoolingPeriod; // Cooling period for Smart Common proposals
uint16 public strategy; // Pass rate for Smart Common proposals
mapping(uint => File) public logoStorages; // Storage for Smart Common logos
SCC0 v2 Compliance Contract
SCC0 v2 Compliance Contract which is deployed by DAism:
contract SCC0License {
string public constant LICENSENAME = "SCC0";
uint8 public constant VERSION = 2;
bool public constant SELFISSUEDTOKEN = false;
bool public constant NORIGHTSEXCEPTREWARDS = true;
bool public constant NOLIABILITY = true;
bool public constant ANONYMITYENSURED = true;
bool public constant OPEN_SOURCE = true;
bool public constant PERMANENTLY_FREE = true;
address public constant GOVERNANCE = 0xe40b05570d2760102c59bf4ffc9b47f921b67a1F;
}
3. SCC0 License Master Contract Implementation
The SCC0 License Manager contract provides the core functionalities for managing license versions and enforcing compliance. It supports:
-
License Version Proposals:
Developers may submit new SCC0 license versions for community approval. Each proposal includes the proposed license address and its version number. -
Version Approval and Registration:
Once approved by the contract owner, new license versions are recorded, ensuring that updated standards are adopted while maintaining backward compatibility. -
Blacklist Management:
Non-compliant dApps/dAIpps can be proposed for blacklisting. Approved proposals mark these addresses as non-compliant, preventing further interactions as SCC0 entities. -
On-Chain Verification:
Functions such asisSCC0Compliant
andisBlacklisted
enable other contracts and governance mechanisms to verify compliance in real time.
Below is the complete implementation of the SCC0 License Manager contract:
// SPDX-License-Identifier: scc0
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
interface IDaism {
function dappToSC(address dApp) external view returns (uint);
}
interface ISCC0License {
function VERSION() external view returns (uint8);
}
contract SCC0LicenseManager is Ownable {
using EnumerableMap for EnumerableMap.UintToAddressMap;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableSet for EnumerableSet.AddressSet;
struct LicenseProposal {
address proposer;
address license;
uint version;
string rejectionReason;
}
struct BlacklistProposal {
address proposer;
address dApp;
string desc;
string rejectionReason;
}
struct Blacklist {
address proposer;
address dApp;
string desc;
bool isEnable;
}
EnumerableMap.UintToAddressMap private licenseMap; // Mapping SCC0 version to address
EnumerableSet.UintSet private unrecommendedSet; // Unrecommended SCC0 version set
mapping(address => Blacklist) public blacklist; // Tracks banned dApps/dAIpps
mapping(address => bool) private pendingVersionSubmission; // Tracks if an address has a pending version submission
mapping(address => bool) private pendingBlacklistSubmission; // Tracks if an address has a pending blacklist submission
mapping(address => LicenseProposal) public pendingLicenseProposals; // mapping of version proposals
EnumerableSet.AddressSet private pendingLicenseProposalSet; //license proposal set
mapping(address => BlacklistProposal) public pendingBlacklistProposals; // mapping of blacklist proposals
EnumerableSet.AddressSet private pendingBlacklistProposalSet; //blacklist proposal set
mapping(address => LicenseProposal) public rejectedLicenseProposals; // mapping of rejected version proposals
mapping(address => BlacklistProposal) public rejectedBlacklistProposals; // mapping of rejected blacklist proposals
address public daismAddress;
event VersionProposed(address indexed proposer, address license, uint version);
event VersionAdded(address indexed license, uint version);
event RejectPendingVersionProposals(address indexed license, uint version);
event UnrecommendedVersionAdded(uint version);
event BlacklistProposed(address indexed proposer, address indexed dApp);
event RejectPendingBlacklistProposals(address indexed dApp);
event Blacklisted(address indexed dApp);
event RemovedFromBlacklist(address indexed dApp);
constructor(address[] memory _licenseAddr, uint[] memory _licenseVersion,address _daismAddress,address _initOwner) Ownable(_initOwner) {
require(_licenseAddr.length > 0 && _licenseAddr.length == _licenseVersion.length, "SCC0LicenseManager: param error");
for (uint i = 0; i < _licenseAddr.length; i++) {
licenseMap.set(_licenseVersion[i], _licenseAddr[i]);
}
daismAddress = _daismAddress;
}
// Submit a new SCC0 license version for approval
function proposeVersion(address _licenseAddr) external {
require(_licenseAddr != address(0) && !pendingLicenseProposalSet.contains(_licenseAddr), "SCC0LicenseManager: license address is null or already exist");
uint8 version = ISCC0License(_licenseAddr).VERSION();
require(version>0&&!licenseMap.contains(version), "SCC0LicenseManager: version error or already exist");
require(!pendingVersionSubmission[msg.sender], "SCC0LicenseManager:sender already pending");
pendingVersionSubmission[msg.sender] = true;
pendingLicenseProposals[_licenseAddr] = LicenseProposal({
proposer: msg.sender,
license: _licenseAddr,
version: version,
rejectionReason: ''
});
pendingLicenseProposalSet.add(_licenseAddr);
emit VersionProposed(msg.sender, _licenseAddr, version);
}
//get pending license proposal info
function getPendingVersionProposals(address _licenseAddr) external view returns(LicenseProposal memory){
return pendingLicenseProposals[_licenseAddr];
}
//get rejected license proposal info
function getRejectedVersionProposals(address _licenseAddr) external view returns(LicenseProposal memory){
return rejectedLicenseProposals[_licenseAddr];
}
//get license proposal total length
function getPendingVersionProposalsLength() external view returns(uint){
return pendingLicenseProposalSet.length();
}
// Retrieve all pending version proposals
function getPendingVersionProposals(uint256 offset, uint256 limit) external view returns (LicenseProposal[] memory) {
uint256 total = pendingLicenseProposalSet.length();
if (offset >= total) {
return new LicenseProposal[](0);
}
uint256 end = offset + limit;
if (end > total) {
end = total;
}
LicenseProposal[] memory proposalsPage = new LicenseProposal[](end - offset);
for (uint256 i = offset; i < end; i++) {
address license = pendingLicenseProposalSet.at(i);
proposalsPage[i - offset] = pendingLicenseProposals[license];
}
return proposalsPage;
}
// Add a new SCC0 license version after approval
function addVersion(address _licenseAddr) external onlyOwner {
require(_licenseAddr != address(0), "SCC0LicenseManager: Invalid address");
LicenseProposal memory proposal = pendingLicenseProposals[_licenseAddr];
require(proposal.license!=address(0), "SCC0LicenseManager: license proposal not exist");
require(!licenseMap.contains(proposal.version), "SCC0LicenseManager: version Already exist");
licenseMap.set(proposal.version, proposal.license);
pendingVersionSubmission[proposal.proposer] = false;
pendingLicenseProposalSet.remove(proposal.license);
delete pendingLicenseProposals[proposal.license];
emit VersionAdded(proposal.license, proposal.version);
}
// reject SCC0 license version proposal
function rejectPendingVersionProposals(address _licenseAddr,string memory _rejectionReason) external onlyOwner {
require(_licenseAddr != address(0), "SCC0LicenseManager: Invalid address");
LicenseProposal memory proposal = pendingLicenseProposals[_licenseAddr];
require(proposal.license!=address(0), "SCC0LicenseManager: license proposal not exist");
pendingVersionSubmission[proposal.proposer] = false;
pendingLicenseProposalSet.remove(proposal.license);
delete pendingLicenseProposals[proposal.license];
rejectedLicenseProposals[_licenseAddr] = LicenseProposal({
proposer: proposal.proposer,
license: proposal.license,
version: proposal.version,
rejectionReason: _rejectionReason
});
emit RejectPendingVersionProposals(proposal.license, proposal.version);
}
// Set unrecommended SCC0 version
function addUnrecommendedVersion(uint _licenseVersion) external onlyOwner {
require(licenseMap.contains(_licenseVersion), "SCC0LicenseManager: Version not exist");
unrecommendedSet.add(_licenseVersion);
emit UnrecommendedVersionAdded(_licenseVersion);
}
// Submit a dApp/dAIpp for blacklisting
function proposeBlacklist(address _dApp,string memory _desc) external {
require(_dApp!=address(0),"SCC0LicenseManager: Invalid address");
require(!pendingBlacklistSubmission[msg.sender], "SCC0LicenseManager: Already pending");
require(!pendingBlacklistProposalSet.contains(_dApp), "SCC0LicenseManager: blacklist already exist");
pendingBlacklistSubmission[msg.sender] = true;
pendingBlacklistProposals[_dApp] = BlacklistProposal({
proposer: msg.sender,
dApp: _dApp,
desc:_desc,
rejectionReason:''
});
pendingBlacklistProposalSet.add(_dApp);
emit BlacklistProposed(msg.sender, _dApp);
}
//get pending blacklist proposal info
function getPendingBlacklistProposals(address _dApp) external view returns(BlacklistProposal memory){
return pendingBlacklistProposals[_dApp];
}
//get rejected blacklist proposal info
function getRejectedBlacklistProposals(address _dApp) external view returns(BlacklistProposal memory){
return rejectedBlacklistProposals[_dApp];
}
//get blacklist proposal total length
function getPendingBlacklistProposalsLength() external view returns(uint){
return pendingBlacklistProposalSet.length();
}
// Retrieve all pending blacklist proposals
function getPendingBlacklistProposals(uint256 offset, uint256 limit) external view returns (BlacklistProposal[] memory) {
uint256 total = pendingBlacklistProposalSet.length();
if (offset >= total) {
return new BlacklistProposal[](0);
}
uint256 end = offset + limit;
if (end > total) {
end = total;
}
BlacklistProposal[] memory proposalsPage = new BlacklistProposal[](end - offset);
for (uint256 i = offset; i < end; i++) {
address dApp = pendingBlacklistProposalSet.at(i);
proposalsPage[i - offset] = pendingBlacklistProposals[dApp];
}
return proposalsPage;
}
// Add a non-compliant dApp/dAIpp to the blacklist after approval
function addToBlacklist(address _dApp) external onlyOwner {
require(_dApp != address(0), "SCC0LicenseManager: Invalid address");
BlacklistProposal memory proposal = pendingBlacklistProposals[_dApp];
require(proposal.dApp!=address(0), "SCC0LicenseManager: blacklist proposal not exist");
blacklist[_dApp] = Blacklist({
proposer:proposal.proposer,
dApp:proposal.dApp,
desc:proposal.desc,
isEnable:true
});
pendingBlacklistSubmission[proposal.proposer] = false;
pendingBlacklistProposalSet.remove(proposal.dApp);
delete pendingBlacklistProposals[proposal.dApp];
emit Blacklisted(_dApp);
}
// reject blacklist proposal
function rejectPendingBlacklistProposals(address _dApp,string memory _rejectionReason) external onlyOwner {
require(_dApp != address(0), "SCC0LicenseManager: Invalid address");
BlacklistProposal memory proposal = pendingBlacklistProposals[_dApp];
require(proposal.dApp!=address(0), "SCC0LicenseManager: blacklist proposal not exist");
pendingBlacklistSubmission[proposal.proposer] = false;
pendingBlacklistProposalSet.remove(proposal.dApp);
delete pendingBlacklistProposals[proposal.dApp];
rejectedBlacklistProposals[_dApp] = BlacklistProposal({
proposer:proposal.proposer,
dApp:proposal.dApp,
desc:proposal.desc,
rejectionReason:_rejectionReason
});
emit RejectPendingBlacklistProposals(proposal.dApp);
}
// Remove a dApp/dAIpp from the blacklist
function removeFromBlacklist(address _dApp) external onlyOwner {
require(_dApp != address(0), "SCC0LicenseManager: Invalid address");
Blacklist storage blacklistTmp = blacklist[_dApp];
require(blacklistTmp.dApp == _dApp,"SCC0LicenseManager: dApp blacklist not exist");
blacklistTmp.isEnable = false;
emit RemovedFromBlacklist(_dApp);
}
// Get license address by version
function getLicenseAddress(uint _licenseVersion) external view returns (address) {
return licenseMap.get(_licenseVersion);
}
// List all SCC0 versions
function getAllVersions() external view returns (uint[] memory) {
return licenseMap.keys();
}
// List all unrecommended SCC0 versions
function getAllUnrecommendedVersions() external view returns (uint[] memory) {
return unrecommendedSet.values();
}
// Check if a dApp is in the blacklist
function isBlacklisted(address _dApp) external view returns (bool) {
return blacklist[_dApp].isEnable;
}
// Check if a dApp is idaism dapp(scc0 v1 version)
function isDaismSC(address _dApp) external view returns (bool) {
bool isBlacklist = blacklist[_dApp].isEnable;
if(isBlacklist) return false;
return IDaism(daismAddress).dappToSC(_dApp)>0;
}
//check if dApp is compliant scc0 license
function isSCC0Compliant(address _dApp, uint _version) external view returns (bool){
bool isBlacklist = blacklist[_dApp].isEnable;
if(licenseMap.contains(_version)&&!isBlacklist) return true;
return false;
}
}
4. Additional Governance and Operational Parameters of SCC0 V1
Beyond the core license and reference implementation contracts, SCC0 includes further parameters to support decentralized governance and community interaction:
-
Smart Common Structure:
A predefined structure (SCInfo
) storing metadata such as the name, symbol, description, manager address, version, and type. -
Member and Proposal Management:
Mappings for recording member details (such as dividend ratios), proposal lifetimes, cooling periods, and decision-making strategies. -
Branding and Identity:
Storage mappings for smart common logos that enhance identity and trust within the ecosystem.
5. Interoperability and On-Chain Verification
The SCC0 framework allows any interacting contract to verify compliance by:
- Checking the declared
LICENSE
constant. - Querying the License Manager’s functions (e.g.,
isSCC0Compliant
). - Ensuring that the dApp/dAIpp is not blacklisted.
These mechanisms promote a trustless and automated approach to enforcing the SCC0 license across decentralized applications.
Reward Distribution Mechanism
To support SCC0-compliant projects, an upgradeable reward distribution system is introduced by SSC0 V1:
- Maintain an array to store external accounts eligible for rewards and their allocation percentages.
- Rewards are not directly sent to external accounts. Instead, they are deposited into the public governance contract.
- External accounts can withdraw funds any time.
mapping(address => Object.Member) public memberInfos; // Stores smart common members and their dividend ratios
uint32 public proposalLifetime; // Validity period of smart common proposals
uint32 public proposalCoolingPeriod; // Cooling period for smart common proposals
uint16 public strategy; // Pass rate for smart common proposals
mapping(uint => File) public logoStorages; // Storage for smart common logos
The reason why neither SSC0 V1 nor SSC0 V2 has introduced “detailed reward rules from Satoshi UTO Fund for smart commons” is that we can neither implement such measures through any centralized review panel approach, nor determine reward amounts through community voting using wallet addresses. The latter approach is even worse - it constitutes a pseudo-decentralized method that would only be employed by self-deceivers or even scammers. We expect some dAIpp take this work in the future, from valuation to prize management.
Compliance Enforcement in Smart Commons
All SCC0-licensed Smart Commons must verify compliance before interacting with another contract. The enforcement mechanism works as follows:
// SPDX-License-Identifier: scc0
pragma solidity ^0.8.20;
interface ISCC0License {
function isSCC0Compliant(address dApp, uint version) external view returns (bool);
function isDaismSC(address dApp) external view returns (bool);
}
interface ISmartCommons {
function SCC0_LICENSE_CONTRACT() external view returns (address);
function SCC0_VERSION() external view returns (uint);
// the called contract method
function otherMethod() external ;
}
contract SmartCommons {
address public constant SCC0_LICENSE_CONTRACT = 0xxxxxxx; // SCC0 License Master Contract address
uint8 public constant SCC0_VERSION = 2; // This contract uses SCC0 V2
address public counterparty;
constructor(address _counterparty) {
counterparty = _counterparty;
}
// If the called contract does not declare the SCC0 License Master Contract address or version
function _checkSCC0WithNotDeclare(address _counterparty) internal view returns(bool){
ISCC0License license = ISCC0License(SCC0_LICENSE_CONTRACT);
return license.isDaismSC(_counterparty);
}
// If the called contract is declare the SCC0 License Master Contract address and version
function _checkSCC0WithDeclare(address _counterparty) internal view returns(bool) {
ISCC0License license = ISCC0License(SCC0_LICENSE_CONTRACT);
return (ISmartCommons(counterparty).SCC0_LICENSE_CONTRACT()==SCC0_LICENSE_CONTRACT &&
license.isSCC0Compliant(_counterparty, ISmartCommons(counterparty).SCC0_VERSION()));
}
// If the called contract is declare the SCC0 License Master Contract address and version
modifier onlySCC0(address _sender) {
require(_checkSCC0WithNotDeclare(_sender) || _checkSCC0WithDeclare(_sender), "Counterparty is not SCC0-compliant");
_;
}
// call counterparty contract
function callCounterparty() public {
// some logic ...
// if not declare SCC0
require(_checkSCC0WithNotDeclare(counterparty),"Counterparty is not SCC0-compliant");
// if declare SCC0
//require(_checkSCC0WithDeclare(counterparty),"Counterparty is not SCC0-compliant");
// some logic ...
}
// other contract call the method must be compliant SCC0
function someFunction() external onlySCC0(msg.sender) {
// Business logic (data exchange, payments, etc.)
}
}
- The
onlySCC0
modifier enforces compliance by checking:- Whether the
counterparty
has declared an SCC0 license. - Whether the
counterparty
is not blacklisted.
- Whether the
- Every SCC0-licensed Smart Commons must apply this check before interacting with another dApp/dAIpp.
Rationale
- License Compliance (
LICENSE
,LICENSENAME
): Ensures smart contracts transparently declare SCC0 adherence. - No Self-Issued Token (
SELFISSUEDTOKEN
): Prevents misleading token issuance claims or any scams. - No Liability (
NOLIABILITY
): Ensures no legal responsibility for SCC0 interactions. - Anonymity Assurance (
ANONYMITYENSURED
): Reinforces that neither ownership nor control can be publicly verified. - No Rights Except Rewards (
NORIGHTSEXCEPTREWARDS
): Confirms no legal claims beyond anonymous rewards. - Version Control (
VERSION
): Allows future iterations of SCC0 compliance to be referenced. - Governance Declaration (
GOVERNANCE
): Defines public governance fund integration. - Enforceability (
onlySCC0
Modifier): Ensures SCC0 validation before contract interactions.
Backwards Compatibility
This EIP does not introduce breaking changes but provides an opt-in mechanism for projects adopting SCC0. Legacy contracts must be redeployed to comply with the new standard.
Security Considerations
- SCC0-compliant contracts disclaim liability, requiring users to acknowledge legal limitations.
- We believe none of upgradeable dApp/dAIpp should be controled by any person(s) ,so multi-sig address is a good way to pass the control to some dAIpps (AIs) in the future. It would be fantastic if we can find a universal solution with some dApp in day one.
- Developers must ensure contract logic aligns with SCC0’s principles.
- The
onlySCC0
modifier enforces compliance in automated contract interactions.
Some dAIpp will enforce the security by auditing every dApp/dAIpp once it’s minted a smart common (v1) or deployed on-chain(v2).
Copyright
Copyright and related rights waived via SCC0.