// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; import {Base64} from "@openzeppelin/contracts/utils/Base64.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; /// @title Spark ERC ($SPARK) /// @notice Fixed-supply ERC-20. No owner, no mint, no tax, no blacklist. /// Exposes ERC-7572 `contractURI()` as an on-chain base64 JSON document. contract SparkToken is ERC20, ERC20Permit { using Strings for string; uint256 public constant TOTAL_SUPPLY = 1_000_000_000 ether; string private _description; string private _image; string private _externalLink; /// @dev ERC-7572 event ContractURIUpdated(); constructor(address recipient, string memory description_, string memory image_, string memory externalLink_) ERC20("Spark ERC", "SPARK") ERC20Permit("Spark ERC") { _description = description_; _image = image_; _externalLink = externalLink_; _mint(recipient, TOTAL_SUPPLY); emit ContractURIUpdated(); } /// @notice ERC-7572 contract-level metadata. function contractURI() external view returns (string memory) { string memory json = string.concat( '{"name":"', name().escapeJSON(), '","symbol":"', symbol().escapeJSON(), '","description":"', _description.escapeJSON(), '","image":"', _image.escapeJSON(), '","external_link":"', _externalLink.escapeJSON(), '"}' ); return string.concat("data:application/json;base64,", Base64.encode(bytes(json))); } }