← Back to Developer Resources

Smart Contract Documentation

Core Contracts

SDM Token (ERC-20)

The SDM token is the native utility token of the Diamondz Shadow ecosystem. It follows the ERC-20 standard with additional functionality for the Proof of Contribution mechanism.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";

contract SDMToken is ERC20, ERC20Burnable, Pausable, AccessControl {
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE");
    
    // Oracle-related variables
    uint256 public viewCount;
    uint256 public subscriberCount;
    uint256 public lastUpdated;
    
    event OracleDataUpdated(uint256 viewCount, uint256 subscriberCount, uint256 timestamp);

    constructor() ERC20("Diamondz Shadow Movies Token", "SDM") {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(PAUSER_ROLE, msg.sender);
        _grantRole(MINTER_ROLE, msg.sender);
        _grantRole(ORACLE_ROLE, msg.sender);
    }

    function pause() public onlyRole(PAUSER_ROLE) {
        _pause();
    }

    function unpause() public onlyRole(PAUSER_ROLE) {
        _unpause();
    }

    function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
        _mint(to, amount);
    }
    
    function updateOracleData(uint256 _viewCount, uint256 _subscriberCount) public onlyRole(ORACLE_ROLE) {
        viewCount = _viewCount;
        subscriberCount = _subscriberCount;
        lastUpdated = block.timestamp;
        
        emit OracleDataUpdated(_viewCount, _subscriberCount, block.timestamp);
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount)
        internal
        whenNotPaused
        override
    {
        super._beforeTokenTransfer(from, to, amount);
    }
}

Key Functions

  • • mint(address to, uint256 amount)
  • • burn(uint256 amount)
  • • updateOracleData(uint256 _viewCount, uint256 _subscriberCount)
  • • pause() / unpause()

Contract Address

0x123...789

View on Explorer

YouTube Oracle

The YouTube Oracle contract is responsible for bringing YouTube metrics on-chain and updating the token economics based on these metrics.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";
import "./interfaces/ISDMToken.sol";

contract YouTubeOracle is AccessControl, ChainlinkClient {
    using Chainlink for Chainlink.Request;
    
    bytes32 public constant ORACLE_UPDATER_ROLE = keccak256("ORACLE_UPDATER_ROLE");
    
    address public sdmToken;
    bytes32 private jobId;
    uint256 private fee;
    
    // YouTube channel data
    string public channelId;
    uint256 public viewCount;
    uint256 public subscriberCount;
    uint256 public lastUpdated;
    
    event OracleDataRequested(bytes32 requestId);
    event OracleDataFulfilled(bytes32 requestId, uint256 viewCount, uint256 subscriberCount);
    
    constructor(address _sdmToken, address _link, address _oracle, string memory _jobId) {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(ORACLE_UPDATER_ROLE, msg.sender);
        
        sdmToken = _sdmToken;
        setChainlinkToken(_link);
        setChainlinkOracle(_oracle);
        jobId = bytes32(bytes(_jobId));
        fee = 0.1 * 10 ** 18; // 0.1 LINK
        
        channelId = "UCxxx..."; // Diamondz Shadow YouTube channel ID
    }
    
    function requestYouTubeData() public onlyRole(ORACLE_UPDATER_ROLE) returns (bytes32 requestId) {
        Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
        
        // Set the URL to perform the GET request on
        request.add("get", string(abi.encodePacked("https://www.googleapis.com/youtube/v3/channels?part=statistics&id=", channelId)));
        
        // Set the path to find the desired data in the API response
        request.add("path", "items.0.statistics.viewCount");
        request.add("path", "items.0.statistics.subscriberCount");
        
        // Send the request
        bytes32 _requestId = sendChainlinkRequestTo(chainlinkOracleAddress(), request, fee);
        emit OracleDataRequested(_requestId);
        return _requestId;
    }
    
    function fulfill(bytes32 _requestId, uint256 _viewCount, uint256 _subscriberCount) public recordChainlinkFulfillment(_requestId) {
        viewCount = _viewCount;
        subscriberCount = _subscriberCount;
        lastUpdated = block.timestamp;
        
        // Update the token contract with the new data
        ISDMToken(sdmToken).updateOracleData(_viewCount, _subscriberCount);
        
        emit OracleDataFulfilled(_requestId, _viewCount, _subscriberCount);
    }
    
    // Manual update function for testing or emergency updates
    function manualUpdate(uint256 _viewCount, uint256 _subscriberCount) public onlyRole(ORACLE_UPDATER_ROLE) {
        viewCount = _viewCount;
        subscriberCount = _subscriberCount;
        lastUpdated = block.timestamp;
        
        // Update the token contract with the new data
        ISDMToken(sdmToken).updateOracleData(_viewCount, _subscriberCount);
    }
}

Key Functions

  • • requestYouTubeData()
  • • fulfill(bytes32 _requestId, uint256 _viewCount, uint256 _subscriberCount)
  • • manualUpdate(uint256 _viewCount, uint256 _subscriberCount)

Contract Address

http://104.198.60.103:6688

View on Explorer

Contribution Tracker

The Contribution Tracker contract is responsible for tracking and rewarding user contributions to the ecosystem.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "./interfaces/ISDMToken.sol";

contract ContributionTracker is AccessControl {
    bytes32 public constant CONTRIBUTOR_ROLE = keccak256("CONTRIBUTOR_ROLE");
    bytes32 public constant VALIDATOR_ROLE = keccak256("VALIDATOR_ROLE");
    
    address public sdmToken;
    
    // Contribution types
    enum ContributionType {
        ContentCreation,
        CommunityEngagement,
        TechnicalContribution,
        GovernanceParticipation,
        CommunityBuilding
    }
    
    // Contribution structure
    struct Contribution {
        address contributor;
        ContributionType contributionType;
        uint256 points;
        string description;
        uint256 timestamp;
        bool validated;
    }
    
    // Mapping from contributor address to their contributions
    mapping(address => Contribution[]) public contributions;
    
    // Mapping from contributor address to their total points
    mapping(address => uint256) public contributionPoints;
    
    // Total points in the system
    uint256 public totalPoints;
    
    // Early adopter multiplier (2x until mainnet launch)
    uint256 public earlyAdopterMultiplier = 2;
    
    event ContributionSubmitted(address indexed contributor, uint256 contributionId, ContributionType contributionType, uint256 points);
    event ContributionValidated(address indexed contributor, uint256 contributionId);
    event PointsRewarded(address indexed contributor, uint256 points, uint256 tokens);
    
    constructor(address _sdmToken) {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
        _grantRole(VALIDATOR_ROLE, msg.sender);
        
        sdmToken = _sdmToken;
    }
    
    function submitContribution(
        ContributionType _type,
        string memory _description
    ) public returns (uint256) {
        // Assign points based on contribution type
        uint256 points;
        if (_type == ContributionType.ContentCreation) {
            points = 50; // Base points for content creation
        } else if (_type == ContributionType.CommunityEngagement) {
            points = 10; // Base points for community engagement
        } else if (_type == ContributionType.TechnicalContribution) {
            points = 30; // Base points for technical contribution
        } else if (_type == ContributionType.GovernanceParticipation) {
            points = 15; // Base points for governance participation
        } else if (_type == ContributionType.CommunityBuilding) {
            points = 20; // Base points for community building
        }
        
        // Apply early adopter multiplier if enabled
        if (earlyAdopterMultiplier > 1) {
            points = points * earlyAdopterMultiplier;
        }
        
        // Create the contribution
        Contribution memory newContribution = Contribution({
            contributor: msg.sender,
            contributionType: _type,
            points: points,
            description: _description,
            timestamp: block.timestamp,
            validated: false
        });
        
        // Add to the contributor's contributions
        contributions[msg.sender].push(newContribution);
        uint256 contributionId = contributions[msg.sender].length - 1;
        
        emit ContributionSubmitted(msg.sender, contributionId, _type, points);
        
        return contributionId;
    }
    
    function validateContribution(address _contributor, uint256 _contributionId) public onlyRole(VALIDATOR_ROLE) {
        require(_contributionId < contributions[_contributor].length, "Contribution does not exist");
        require(!contributions[_contributor][_contributionId].validated, "Contribution already validated");
        
        // Mark as validated
        contributions[_contributor][_contributionId].validated = true;
        
        // Add points to contributor's total
        uint256 points = contributions[_contributor][_contributionId].points;
        contributionPoints[_contributor] += points;
        totalPoints += points;
        
        emit ContributionValidated(_contributor, _contributionId);
    }
    
    function distributeRewards(uint256 _tokenAmount) public onlyRole(DEFAULT_ADMIN_ROLE) {
        require(totalPoints > 0, "No contributions to reward");
        
        for (uint256 i = 0; i < getRoleMembers(CONTRIBUTOR_ROLE).length; i++) {
            address contributor = getRoleMembers(CONTRIBUTOR_ROLE)[i];
            
            if (contributionPoints[contributor] > 0) {
                // Calculate tokens based on proportion of total points
                uint256 tokens = (_tokenAmount * contributionPoints[contributor]) / totalPoints;
                
                // Mint tokens to the contributor
                ISDMToken(sdmToken).mint(contributor, tokens);
                
                emit PointsRewarded(contributor, contributionPoints[contributor], tokens);
                
                // Reset points after distribution
                contributionPoints[contributor] = 0;
            }
        }
        
        // Reset total points
        totalPoints = 0;
    }
    
    function getContributionsCount(address _contributor) public view returns (uint256) {
        return contributions[_contributor].length;
    }
    
    function getContribution(address _contributor, uint256 _contributionId) public view returns (
        ContributionType contributionType,
        uint256 points,
        string memory description,
        uint256 timestamp,
        bool validated
    ) {
        require(_contributionId < contributions[_contributor].length, "Contribution does not exist");
        
        Contribution memory contribution = contributions[_contributor][_contributionId];
        return (
            contribution.contributionType,
            contribution.points,
            contribution.description,
            contribution.timestamp,
            contribution.validated
        );
    }
    
    function setEarlyAdopterMultiplier(uint256 _multiplier) public onlyRole(DEFAULT_ADMIN_ROLE) {
        earlyAdopterMultiplier = _multiplier;
    }
    
    function getRoleMembers(bytes32 role) internal view returns (address[] memory) {
        uint256 count = getRoleMemberCount(role);
        address[] memory members = new address[](count);
        
        for (uint256 i = 0; i < count; i++) {
            members[i] = getRoleMember(role, i);
        }
        
        return members;
    }
}

Key Functions

  • • submitContribution(ContributionType _type, string memory _description)
  • • validateContribution(address _contributor, uint256 _contributionId)
  • • distributeRewards(uint256 _tokenAmount)

Contract Address

0x789...def

View on Explorer

Contract Interfaces

Our contracts use standardized interfaces to ensure interoperability and easy integration.

ISDMToken.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

interface ISDMToken {
    function mint(address to, uint256 amount) external;
    function burn(uint256 amount) external;
    function updateOracleData(uint256 _viewCount, uint256 _subscriberCount) external;
}

For technical support or contract inquiries:

development@diamondzshadow.com