S Price: $0.499347 (-0.39%)

Contract Diff Checker

Contract Name:
CoderativeA

Contract Source Code:

File 1 of 1 : CoderativeA

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

/*
   11111111111           111111 
   11                       111
   11                       111
   11         11111111111   111
   11                       111
   11                       111
   11111111111              111
   
   CODERATIVE-1
*/

/*
 * DISCLAIMER: This contract is designed to encourage users to interact with blockchain technology 
 * on the Sonic network, demonstrating its speed and low costs. Users are urged to thoroughly review 
 * the contract and understand its mechanics before interacting. By using this contract, you agree
 * that you are solely responsible for any actions taken and their outcomes. Blockchain interactions
 * are inherently risky, and this contract provides no guarantees.
 * 
 * Official Website: https://coderativesonic.github.io/nft-art-generator/
 * Twitter: @0xcoderative
 */

/**
 * @dev Provides a set of functions to operate with Base64 strings.
 */
library Base64 {
    /**
     * @dev Base64 Encoding/Decoding Table
     * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648
     */
    string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    string internal constant _TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

    /**
     * @dev Converts a `bytes` to its Bytes64 `string` representation.
     */
    function encode(bytes memory data) internal pure returns (string memory) {
        return _encode(data, _TABLE, true);
    }

    /**
     * @dev Converts a `bytes` to its Bytes64Url `string` representation.
     * Output is not padded with `=` as specified in https://www.rfc-editor.org/rfc/rfc4648[rfc4648].
     */
    function encodeURL(bytes memory data) internal pure returns (string memory) {
        return _encode(data, _TABLE_URL, false);
    }

    /**
     * @dev Internal table-agnostic conversion
     */
    function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) {
        if (data.length == 0) return "";

        uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3;

        string memory result = new string(resultLength);

        assembly ("memory-safe") {
            let tablePtr := add(table, 1)
            let resultPtr := add(result, 0x20)
            let dataPtr := data
            let endPtr := add(data, mload(data))

            let afterPtr := add(endPtr, 0x20)
            let afterCache := mload(afterPtr)
            mstore(afterPtr, 0x00)

            for {

            } lt(dataPtr, endPtr) {

            } {
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1)

                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1)

                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                resultPtr := add(resultPtr, 1)

                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
                resultPtr := add(resultPtr, 1)
            }

            mstore(afterPtr, afterCache)

            if withPadding {
                switch mod(mload(data), 3)
                case 1 {
                    mstore8(sub(resultPtr, 1), 0x3d)
                    mstore8(sub(resultPtr, 2), 0x3d)
                }
                case 2 {
                    mstore8(sub(resultPtr, 1), 0x3d)
                }
            }
        }

        return result;
    }
}

/**
 * @title ERC721 Standard Implementation
 * @notice Base implementation of ERC721 with added features for enumeration.
 */
contract ERC721 {
    // Events emitted for key actions in ERC721
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    // Mapping to store the owners of tokens
    mapping(uint256 => address) private _owners;

    // Mapping to store balances of addresses
    mapping(address => uint256) private _balances;

    // Mapping for token approvals
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping for operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    /**
     * @notice Returns the balance of the given address.
     * @param owner The address to query.
     * @return uint256 The token balance.
     */
    function balanceOf(address owner) public view returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    /**
     * @notice Returns the owner of the specified token ID.
     * @param tokenId The token ID to query.
     * @return address The owner address.
     */
    function ownerOf(uint256 tokenId) public view returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    /**
     * @notice Internal function to transfer ownership of a token.
     * @param from The current owner of the token.
     * @param to The new owner of the token.
     * @param tokenId The token ID to transfer.
     */
    function _transfer(address from, address to, uint256 tokenId) internal {
        require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        _beforeTokenTransfer(from, to, tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        _afterTokenTransfer(from, to, tokenId);
    }

    /**
     * @notice Internal function to mint a new token.
     * @param to The address to receive the minted token.
     * @param tokenId The token ID to mint.
     */
    function _mint(address to, uint256 tokenId) internal {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

        _afterTokenTransfer(address(0), to, tokenId);
    }

    /**
     * @notice Checks if a token ID exists.
     * @param tokenId The token ID to check.
     * @return bool True if the token exists, false otherwise.
     */
    function _exists(uint256 tokenId) internal view returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Hook that is called before any token transfer.
     */
    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual {}

    /**
     * @dev Hook that is called after any token transfer.
     */
    function _afterTokenTransfer(address from, address to, uint256 tokenId) internal virtual {}
}

/**
 * @title Ownable Contract
 * @notice Basic ownership functionality for the contract.
 */
contract Ownable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor(address initialOwner) {
        _transferOwnership(initialOwner);
    }

    function owner() public view returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(owner() == msg.sender, "Ownable: caller is not the owner");
        _;
    }

    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    function renounceOwnership() public onlyOwner {
        _transferOwnership(address(0));
    }

    function _transferOwnership(address newOwner) internal {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

/**
 * @title ERC721Enumerable
 * @notice ERC721 implementation with token enumeration functionality.
 */
contract ERC721Enumerable is ERC721 {
    uint256[] private _allTokens;
    mapping(uint256 => uint256) private _allTokensIndex;
    mapping(address => uint256[]) private _ownedTokens;
    mapping(uint256 => uint256) private _ownedTokensIndex;

    function totalSupply() public view returns (uint256) {
        return _allTokens.length;
    }

    function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
        require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
        return _ownedTokens[owner][index];
    }

    function tokenByIndex(uint256 index) public view returns (uint256) {
        require(index < _allTokens.length, "ERC721Enumerable: global index out of bounds");
        return _allTokens[index];
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal virtual override {
        super._beforeTokenTransfer(from, to, tokenId);

        if (from == address(0)) {
            _addTokenToAllTokensEnumeration(tokenId);
        } else if (from != to) {
            _removeTokenFromOwnerEnumeration(from, tokenId);
        }
        if (to == address(0)) {
            _removeTokenFromAllTokensEnumeration(tokenId);
        } else if (to != from) {
            _addTokenToOwnerEnumeration(to, tokenId);
        }
    }

    function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
        _ownedTokens[to].push(tokenId);
        _ownedTokensIndex[tokenId] = _ownedTokens[to].length - 1;
    }

    function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
        uint256 lastTokenIndex = _ownedTokens[from].length - 1;
        uint256 tokenIndex = _ownedTokensIndex[tokenId];

        if (tokenIndex != lastTokenIndex) {
            uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
            _ownedTokens[from][tokenIndex] = lastTokenId;
            _ownedTokensIndex[lastTokenId] = tokenIndex;
        }

        _ownedTokens[from].pop();
        delete _ownedTokensIndex[tokenId];
    }

    function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
        _allTokensIndex[tokenId] = _allTokens.length;
        _allTokens.push(tokenId);
    }

    function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
        uint256 lastTokenIndex = _allTokens.length - 1;
        uint256 tokenIndex = _allTokensIndex[tokenId];

        uint256 lastTokenId = _allTokens[lastTokenIndex];

        _allTokens[tokenIndex] = lastTokenId;
        _allTokensIndex[lastTokenId] = tokenIndex;

        _allTokens.pop();
        delete _allTokensIndex[tokenId];
    }
}

/**
 * @title CoderativeA
 * @notice Main contract for generative art NFTs on the Sonic network.
 */
contract CoderativeA is ERC721Enumerable, Ownable {
    uint256 private _tokenIds;
    mapping(address => bool) private _hasMinted;
    mapping(uint256 => string) public tokenData;

    uint256 private constant MAX_SUPPLY = 5000;

    string private _name = "Coderative-A Collection";
    string private _symbol = "CAC";

    event NFTMinted(address indexed minter, uint256 indexed tokenId, string data);

    error AlreadyMinted();
    error MaxSupplyReached();

    constructor() Ownable(msg.sender) {}

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function mint() external {
        if (_hasMinted[msg.sender]) revert AlreadyMinted();
        if (_tokenIds >= MAX_SUPPLY) revert MaxSupplyReached();

        _hasMinted[msg.sender] = true;

        uint256 tokenId = _tokenIds;
        _tokenIds++;

        string memory data = _generateArtData(msg.sender);
        tokenData[tokenId] = data;

        emit NFTMinted(msg.sender, tokenId, data);

        _mint(msg.sender, tokenId);
    }

    function _generateArtData(address minter) internal view returns (string memory) {
        bytes32 blockHash = blockhash(block.number - 1);
        uint256 gradientAngle = uint256(keccak256(abi.encodePacked(blockHash, minter))) % 360;
        uint256 noiseLevel = uint256(keccak256(abi.encodePacked(blockHash, minter, "noise"))) % 100;
        uint256 colorSeed = uint256(keccak256(abi.encodePacked(blockHash, minter, "colors")));

        return string(abi.encodePacked(
            "{",
            "\"name\":\"Coderative-A Token\",",
            "\"description\":\"A generative art NFT\",",
            "\"attributes\":{",
            "\"angle\":", _toString(gradientAngle), ",",
            "\"noise\":", _toString(noiseLevel), ",",
            "\"color\":", _toString(colorSeed),
            "}}"
        ));
    }

    function _toString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    function tokenURI(uint256 tokenId) public view returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory data = tokenData[tokenId];
        return string(abi.encodePacked("data:application/json;base64,", Base64.encode(bytes(data))));
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):