neo-devpack-solidity 0.22.0

Production-focused Solidity-to-NeoVM compilation system
Documentation
{
  "language": "Solidity",
  "sources": {
    "contracts/Framework.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title Neo N3 Framework\n * @dev Extended framework for Neo N3 Solidity contracts.\n *\n * `FrameworkBase.sol` is designed to keep manifests minimally-permissioned by\n * default. This `Framework.sol` contract previously exposed a fully dynamic\n * `callContract` surface, but that forced wildcard permissions in the manifest\n * (`{\"contract\":\"*\",\"methods\":\"*\"}`), which is a security anti-pattern.\n *\n * STRICT-MANIFEST MODE (current default):\n *   `callContract` is intentionally disabled (reverts at runtime) so that the\n *   compiler can infer precise contract-hash permissions from explicit\n *   `NativeCalls.*` or `Syscalls.contractCall(KNOWN_HASH, ...)` calls.\n *\n * If you need dynamic calls, use one of these alternatives:\n *   1. `Syscalls.contractCall(knownHash, method, params)` with a constant hash\n *      — produces exact manifest permissions.\n *   2. `NativeCalls.*` wrappers for native Neo contracts (GAS, NEO, etc.)\n *      — produces exact native contract permissions.\n *   3. Compile with `--manifest-permissions` to supply explicit overrides\n *      when truly dynamic dispatch is unavoidable.\n */\n\nimport \"./FrameworkBase.sol\";\nimport \"../libraries/Neo.sol\";\n\ncontract Framework is FrameworkBase {\n    /**\n     * @dev Call another contract (fully dynamic).\n     *\n     * Because both the target and method can be user-controlled, Neo N3\n     * permission inference cannot restrict this safely without wildcards.\n     */\n    function callContract(address contractHash, string calldata method, bytes calldata params)\n        public\n        withWitness\n        returns (bytes memory)\n    {\n        contractHash;\n        method;\n        params;\n        revert(\n            \"Framework: dynamic call surface disabled in strict-manifest mode; use explicit NativeCalls/Syscalls wrappers\"\n        );\n    }\n}\n\n"
    },
    "contracts/FrameworkBase.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title Neo N3 Framework Base\n * @dev Base framework providing Neo N3 blockchain integration for Solidity contracts.\n *\n * This base intentionally avoids exposing fully-dynamic contract call helpers\n * (dynamic target + dynamic method name), because those force full wildcard\n * permissions in the Neo N3 manifest (`{\"contract\":\"*\",\"methods\":\"*\"}`).\n *\n * If you need a public dynamic call surface, use `Framework.sol` instead.\n */\n\nimport \"./Syscalls.sol\";\nimport \"./NativeCalls.sol\";\nimport \"../libraries/Neo.sol\";\nimport \"../libraries/Storage.sol\";\nimport \"../libraries/Runtime.sol\";\n\ncontract FrameworkBase {\n    using Neo for *;\n    using Storage for *;\n    using Runtime for *;\n\n    // Framework state\n    address private _owner;\n    bool private _initialized;\n    uint256 private _version;\n\n    // Neo N3 integration\n    bytes4 private constant NEO_MAGIC = 0x3346454E; // \"NEF3\"\n    uint256 private constant MIN_GAS_LIMIT = 20000000; // 0.2 GAS\n\n    // Events\n    event FrameworkInitialized(address indexed owner, uint256 version);\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n    event ContractUpgraded(uint256 indexed oldVersion, uint256 indexed newVersion);\n    event EmergencyStop(address indexed caller, string reason);\n\n    // Modifiers\n    modifier onlyOwner() {\n        require(msg.sender == _owner, \"Framework: caller is not the owner\");\n        _;\n    }\n\n    modifier whenInitialized() {\n        require(_initialized, \"Framework: not initialized\");\n        _;\n    }\n\n    modifier withWitness() {\n        require(Runtime.checkWitness(msg.sender), \"Framework: invalid witness\");\n        _;\n    }\n\n    modifier withGasLimit(uint256 minGas) {\n        require(Runtime.gasLeft() >= minGas, \"Framework: insufficient gas\");\n        _;\n    }\n\n    /**\n     * @dev Initialize the framework\n     */\n    constructor() {\n        _owner = msg.sender;\n        _version = 1;\n        _initialized = true;\n\n        emit FrameworkInitialized(_owner, _version);\n    }\n\n    /**\n     * @dev Get framework version\n     */\n    function version() public view returns (uint256) {\n        return _version;\n    }\n\n    /**\n     * @dev Get contract owner\n     */\n    function owner() public view returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Check if framework is initialized\n     */\n    function initialized() public view returns (bool) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Transfer ownership of the contract\n     */\n    function transferOwnership(address newOwner) public onlyOwner withWitness {\n        require(newOwner != address(0), \"Framework: new owner is the zero address\");\n        require(newOwner != _owner, \"Framework: new owner is the same as current owner\");\n\n        emit OwnershipTransferred(_owner, newOwner);\n        _owner = newOwner;\n    }\n\n    /**\n     * @dev Renounce ownership of the contract\n     */\n    function renounceOwnership() public onlyOwner withWitness {\n        emit OwnershipTransferred(_owner, address(0));\n        _owner = address(0);\n    }\n\n    /**\n     * @dev Upgrade contract version\n     */\n    function upgradeContract(bytes calldata nef, bytes calldata manifest, uint256 newVersion)\n        public\n        onlyOwner\n        withWitness\n        withGasLimit(MIN_GAS_LIMIT)\n    {\n        require(newVersion > _version, \"Framework: version must be higher\");\n        require(nef.length > 0, \"Framework: NEF cannot be empty\");\n        require(manifest.length > 0, \"Framework: manifest cannot be empty\");\n\n        uint256 oldVersion = _version;\n        _version = newVersion;\n\n        // Call ContractManagement.update\n        NativeCalls.updateContract(nef, manifest);\n\n        emit ContractUpgraded(oldVersion, newVersion);\n    }\n\n    /**\n     * @dev Emergency stop function\n     */\n    function emergencyStop(string calldata reason) public onlyOwner withWitness {\n        // Emit emergency event\n        emit EmergencyStop(msg.sender, reason);\n\n        // Optional: Call self-destruct via ContractManagement\n        // NativeCalls.destroyContract();\n    }\n\n    /**\n     * @dev Get current block information.\n     * @notice `hash` and `merkleRoot` return zero because Neo N3 does not\n     *         expose per-block hash or merkle root via lightweight syscalls.\n     *         Use `Syscalls.contractCall(LEDGER_CONTRACT, \"getBlock\", ...)`\n     *         for full block data when needed.\n     */\n    function getCurrentBlock()\n        public\n        view\n        returns (uint256 index, bytes32 hash, uint256 timestamp, bytes32 merkleRoot)\n    {\n        index = Syscalls.getCurrentIndex();\n        hash = bytes32(0);           // Not available via syscall; see @notice\n        timestamp = Syscalls.getTime();\n        merkleRoot = bytes32(0);     // Not available via syscall; see @notice\n    }\n\n    /**\n     * @dev Get transaction information\n     */\n    function getTransaction(bytes32 txHash)\n        public\n        view\n        returns (bytes32 hash, uint256 nonce, address sender, uint256 gasLimit, uint256 gasPrice)\n    {\n        // Neo N3 exposes full transaction information via the Ledger native contract,\n        // but its shape does not map 1:1 to EVM transaction fields.\n        //\n        // Provide a minimal, deterministic subset that is safe for diagnostics-style use.\n        Syscalls.Transaction memory tx = Syscalls.getTransaction(txHash);\n        hash = tx.hash;\n        nonce = tx.nonce;\n        sender = tx.sender;\n        gasLimit = tx.systemFee;\n        gasPrice = Neo.getGasPrice();\n    }\n\n    /**\n     * @dev Get contract balance (GAS)\n     */\n    function getBalance() public view returns (uint256) {\n        return Neo.getGasBalance(address(this));\n    }\n\n    /**\n     * @dev Get NEO balance\n     */\n    function getNeoBalance(address account) public view returns (uint256) {\n        return Neo.getNeoBalance(account);\n    }\n\n    /**\n     * @dev Transfer GAS to another address\n     */\n    function transferGas(address to, uint256 amount) public onlyOwner withWitness {\n        require(to != address(0), \"Framework: cannot transfer to zero address\");\n        require(amount > 0, \"Framework: amount must be greater than zero\");\n\n        bool success = Neo.transferGas(address(this), to, amount);\n        require(success, \"Framework: GAS transfer failed\");\n    }\n\n    /**\n     * @dev Advanced storage operations\n     */\n    function setStorageValue(bytes calldata key, bytes calldata value) public onlyOwner {\n        Storage.put(key, value);\n    }\n\n    function getStorageValue(bytes calldata key) public view returns (bytes memory) {\n        return Storage.get(key);\n    }\n\n    function deleteStorageValue(bytes calldata key) public onlyOwner {\n        Storage.remove(key);\n    }\n\n    /**\n     * @dev Iterate through storage\n     */\n    function findStorageValues(bytes calldata prefix) public view returns (bytes[] memory values) {\n        Storage.Iterator memory iterator = Storage.find(prefix);\n        bytes[] memory temp = new bytes[](100); // Max 100 results\n        uint256 count = 0;\n\n        while (iterator.next() && count < 100) {\n            temp[count] = iterator.value();\n            count++;\n        }\n\n        values = new bytes[](count);\n        for (uint256 i = 0; i < count; i++) {\n            values[i] = temp[i];\n        }\n    }\n\n    /**\n     * @dev Deploy new contract\n     */\n    function deployContract(bytes calldata nef, bytes calldata manifest)\n        public\n        onlyOwner\n        withWitness\n        withGasLimit(MIN_GAS_LIMIT)\n        returns (address)\n    {\n        return NativeCalls.deployContract(nef, manifest);\n    }\n\n    /**\n     * @dev Get contract information via ContractManagement.getContract\n     */\n    function getContractInfo(address contractHash)\n        public\n        view\n        returns (string memory name, bytes memory script, bytes memory manifest)\n    {\n        NativeCalls.ContractState memory state = NativeCalls.getContract(contractHash);\n        name = \"Contract\"; // Neo N3 ContractState does not expose a name field\n        script = state.nef;\n        manifest = state.manifest;\n    }\n\n    /**\n     * @dev Verify signature\n     */\n    function verifySignature(bytes32 hash, bytes calldata publicKey, bytes calldata signature)\n        public\n        pure\n        returns (bool)\n    {\n        return Neo.verifySignature(hash, publicKey, signature);\n    }\n\n    /**\n     * @dev Get random number (using Neo's randomness)\n     */\n    function getRandom() public view returns (uint256) {\n        return Neo.getRandom();\n    }\n\n    /**\n     * @dev Check if account is committee member\n     */\n    function isCommittee(address account) public view returns (bool) {\n        return NativeCalls.isCommittee(account);\n    }\n\n    /**\n     * @dev Get current committee members\n     */\n    function getCommittee() public view returns (bytes[] memory) {\n        return Neo.getCommittee();\n    }\n\n    /**\n     * @dev Batch operations for gas efficiency\n     */\n    function batchStorageOperations(bytes[] calldata keys, bytes[] calldata values, bool[] calldata isDelete)\n        public\n        onlyOwner\n    {\n        require(keys.length == values.length, \"Framework: array length mismatch\");\n        require(keys.length == isDelete.length, \"Framework: array length mismatch\");\n        require(keys.length > 0, \"Framework: empty arrays\");\n        require(keys.length <= 100, \"Framework: too many operations\");\n\n        for (uint256 i = 0; i < keys.length; i++) {\n            if (isDelete[i]) {\n                Storage.remove(keys[i]);\n            } else {\n                Storage.put(keys[i], values[i]);\n            }\n        }\n    }\n\n    /**\n     * @dev Get gas consumption for operation\n     */\n    function estimateGas(bytes calldata operation) public view returns (uint256) {\n        // Base gas estimation based on operation size.\n        uint256 baseGas = 1000000; // 0.01 GAS\n        uint256 dataGas = operation.length * 1000; // 0.00001 GAS per byte\n        return baseGas + dataGas;\n    }\n\n    /**\n     * @dev Get current gas price\n     */\n    function getGasPrice() public view returns (uint256) {\n        return Neo.getGasPrice();\n    }\n\n    /**\n     * @dev Get storage price per byte\n     */\n    function getStoragePrice() public view returns (uint256) {\n        return Neo.getStoragePrice();\n    }\n\n    /**\n     * @dev Framework diagnostics\n     */\n    function getDiagnostics()\n        public\n        view\n        returns (\n            uint256 currentBlock,\n            uint256 gasBalance,\n            uint256 neoBalance,\n            bool isCommitteeMember\n        )\n    {\n        currentBlock = block.number;\n        gasBalance = Neo.getGasBalance(address(this));\n        neoBalance = Neo.getNeoBalance(address(this));\n        isCommitteeMember = isCommittee(address(this));\n    }\n\n    /**\n     * @dev Framework metadata\n     */\n    function getFrameworkInfo()\n        public\n        pure\n        returns (string memory name, string memory version, string memory author, string memory repository)\n    {\n        return (\n            \"Neo N3 Solidity Framework\",\n            \"1.0.0\",\n            \"Jimmy <jimmy@r3e.network>\",\n            \"https://github.com/r3e-network/neo-devpack-solidity\"\n        );\n    }\n}\n"
    },
    "contracts/NativeCalls.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title Neo N3 Native Contract Calls\n * @dev Direct integration with Neo N3 native contracts\n * @author Jimmy <jimmy@r3e.network>\n * \n * This library provides direct access to Neo N3 native contracts:\n * - NEO: Native NEO token and governance\n * - GAS: Native GAS token\n * - ContractManagement: Contract deployment and management\n * - Policy: Network policy management\n * - Oracle: Oracle services\n * - RoleManagement: Role and permission management\n * - Notary: Notary deposit services\n * - Treasury: Treasury funds management\n * - Ledger: Blockchain data access\n *\n * CryptoLib and StdLib methods are exposed through `Syscalls.sol` directly\n * (e.g. `Syscalls.sha256()`, `Syscalls.serialize()`, `Syscalls.base64Encode()`).\n * Their contract hash constants are defined here for reference.\n */\n\nimport \"./Syscalls.sol\";\n\nlibrary NativeCalls {\n    using Syscalls for *;\n    \n    // Native contract script hashes (deterministic, identical on all Neo N3 networks)\n    address constant NEO_CONTRACT = 0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5;\n    address constant GAS_CONTRACT = 0xd2a4cff31913016155e38e474a2c06d08be276cf;\n    address constant CONTRACT_MANAGEMENT = 0xfffdc93764dbaddd97c48f252a53ea4643faa3fd;\n    address constant POLICY_CONTRACT = 0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b;\n    address constant ORACLE_CONTRACT = 0xfe924b7cfe89ddd271abaf7210a80a7e11178758;\n    address constant ROLE_MANAGEMENT = 0x49cf4e5378ffcd4dec034fd98a174c5491e395e2;\n    address constant NOTARY_CONTRACT = 0xc1e14f19c3e60d0b9244d06dd7ba9b113135ec3b;\n    address constant TREASURY_CONTRACT = 0x156326f25b1b5d839a4d326aeaa75383c9563ac1;\n    address constant LEDGER_CONTRACT = 0xda65b600f7124ce6c79950c1772a36403104f2be;\n    address constant CRYPTO_LIB = 0x726cb6e0cd8628a1350a611384688911ab75f51b;\n    address constant STD_LIB = 0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0;\n    \n    // ========== NEO Token Native Contract ==========\n    \n    /**\n     * @dev Get NEO total supply\n     */\n    function neoTotalSupply() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"totalSupply\", \"\");\n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Get NEO balance of account\n     */\n    function neoBalanceOf(address account) internal view returns (uint256) {\n        bytes memory params = abi.encode(account);\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"balanceOf\", params);\n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Transfer NEO tokens\n     */\n    function neoTransfer(address from, address to, uint256 amount, bytes memory data) \n        internal \n        returns (bool) \n    {\n        bytes memory params = abi.encode(from, to, amount, data);\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"transfer\", params);\n        return abi.decode(result, (bool));\n    }\n    \n    /**\n     * @dev Get NEO decimals\n     */\n    function neoDecimals() internal view returns (uint8) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"decimals\", \"\");\n        return abi.decode(result, (uint8));\n    }\n    \n    /**\n     * @dev Get NEO symbol\n     */\n    function neoSymbol() internal view returns (string memory) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"symbol\", \"\");\n        return abi.decode(result, (string));\n    }\n    \n    /**\n     * @dev Vote for validator\n     */\n    function vote(address account, bytes memory publicKey) internal returns (bool) {\n        bytes memory params = abi.encode(account, publicKey);\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"vote\", params);\n        return abi.decode(result, (bool));\n    }\n    \n    /**\n     * @dev Get candidates\n     *\n     * Neo N3: `NeoToken.getCandidates()` returns `(ECPoint publicKey, BigInteger votes)[]`\n     * for the first 256 registered (non-blocked) candidates.\n     */\n    function getCandidates() internal view returns (NeoCandidate[] memory) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"getCandidates\", \"\");\n        return abi.decode(result, (NeoCandidate[]));\n    }\n\n    /**\n     * @dev Get all registered candidates (iterator)\n     */\n    function getAllCandidates() internal view returns (Syscalls.Iterator memory) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"getAllCandidates\", \"\");\n        return abi.decode(result, (Syscalls.Iterator));\n    }\n\n    /**\n     * @dev Get candidate vote count (returns -1 if not found)\n     */\n    function getCandidateVote(bytes memory publicKey) internal view returns (int256) {\n        bytes memory params = abi.encode(publicKey);\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"getCandidateVote\", params);\n        return abi.decode(result, (int256));\n    }\n    \n    /**\n     * @dev Register as candidate\n     */\n    function registerCandidate(bytes memory publicKey) internal returns (bool) {\n        bytes memory params = abi.encode(publicKey);\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"registerCandidate\", params);\n        return abi.decode(result, (bool));\n    }\n    \n    /**\n     * @dev Unregister candidate\n     */\n    function unregisterCandidate(bytes memory publicKey) internal returns (bool) {\n        bytes memory params = abi.encode(publicKey);\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"unregisterCandidate\", params);\n        return abi.decode(result, (bool));\n    }\n    \n    /**\n     * @dev Get GAS per block\n     */\n    function getGasPerBlock() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"getGasPerBlock\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get register price for candidates\n     */\n    function getRegisterPrice() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"getRegisterPrice\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Set register price for candidates (committee only)\n     */\n    function setRegisterPrice(uint256 value) internal {\n        bytes memory params = abi.encode(value);\n        Syscalls.contractCall(NEO_CONTRACT, \"setRegisterPrice\", params);\n    }\n    \n    /**\n     * @dev Set GAS per block (committee only)\n     */\n    function setGasPerBlock(uint256 gasPerBlock) internal {\n        bytes memory params = abi.encode(gasPerBlock);\n        Syscalls.contractCall(NEO_CONTRACT, \"setGasPerBlock\", params);\n    }\n    \n    /**\n     * @dev Get account state\n     *\n     * Neo N3: `NeoToken.getAccountState(UInt160)` returns `NeoAccountState?` (nullable).\n     * The compiler lowers this helper to return a default (zeroed) struct when the\n     * native contract returns `null`, matching Solidity's \"missing mapping key\"\n     * semantics.\n     */\n    function getAccountState(address account) internal view returns (AccountState memory) {\n        bytes memory params = abi.encode(account);\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"getAccountState\", params);\n        return abi.decode(result, (AccountState));\n    }\n\n    /**\n     * @dev Get unclaimed GAS for account at a specific block height\n     */\n    function unclaimedGas(address account, uint256 end) internal view returns (uint256) {\n        bytes memory params = abi.encode(account, end);\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"unclaimedGas\", params);\n        return abi.decode(result, (uint256));\n    }\n    \n    // ========== GAS Token Native Contract ==========\n    \n    /**\n     * @dev Get GAS total supply\n     */\n    function gasTotalSupply() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(GAS_CONTRACT, \"totalSupply\", \"\");\n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Get GAS balance of account\n     */\n    function gasBalanceOf(address account) internal view returns (uint256) {\n        bytes memory params = abi.encode(account);\n        bytes memory result = Syscalls.contractCall(GAS_CONTRACT, \"balanceOf\", params);\n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Transfer GAS tokens\n     */\n    function gasTransfer(address from, address to, uint256 amount, bytes memory data) \n        internal \n        returns (bool) \n    {\n        bytes memory params = abi.encode(from, to, amount, data);\n        bytes memory result = Syscalls.contractCall(GAS_CONTRACT, \"transfer\", params);\n        return abi.decode(result, (bool));\n    }\n    \n    /**\n     * @dev Get GAS decimals\n     */\n    function gasDecimals() internal view returns (uint8) {\n        bytes memory result = Syscalls.contractCall(GAS_CONTRACT, \"decimals\", \"\");\n        return abi.decode(result, (uint8));\n    }\n    \n    /**\n     * @dev Get GAS symbol\n     */\n    function gasSymbol() internal view returns (string memory) {\n        bytes memory result = Syscalls.contractCall(GAS_CONTRACT, \"symbol\", \"\");\n        return abi.decode(result, (string));\n    }\n    \n    // ========== Contract Management Native Contract ==========\n    \n    /**\n     * @dev Deploy new contract\n     */\n    function deployContract(bytes memory nef, bytes memory manifest) internal returns (address) {\n        bytes memory params = abi.encode(nef, manifest);\n        bytes memory result = Syscalls.contractCall(CONTRACT_MANAGEMENT, \"deploy\", params);\n        return abi.decode(result, (address));\n    }\n\n    /**\n     * @dev Deploy new contract and pass deployment data to `_deploy(data, false)`\n     *\n     * The `data` parameter is forwarded to the deployed contract's `_deploy(data, update)` entrypoint\n     * (with `update == false`). For neo-devpack-solidity-compiled contracts with parameterised constructors,\n     * this is typically a JSON-encoded array (e.g. `[7]`) or StdLib.serialize(...) bytes.\n     */\n    function deployContract(bytes memory nef, bytes memory manifest, bytes memory data)\n        internal\n        returns (address)\n    {\n        bytes memory params = abi.encode(nef, manifest, data);\n        bytes memory result = Syscalls.contractCall(CONTRACT_MANAGEMENT, \"deploy\", params);\n        return abi.decode(result, (address));\n    }\n    \n    /**\n     * @dev Update contract\n     */\n    function updateContract(bytes memory nef, bytes memory manifest) internal {\n        bytes memory params = abi.encode(nef, manifest);\n        Syscalls.contractCall(CONTRACT_MANAGEMENT, \"update\", params);\n    }\n\n    /**\n     * @dev Update contract and pass update data to `_deploy(data, true)`\n     *\n     * The `data` parameter is forwarded to the updated contract's `_deploy(data, update)` entrypoint\n     * (with `update == true`). This can be used for migration flows when a contract implements custom\n     * `_deploy` logic.\n     */\n    function updateContract(bytes memory nef, bytes memory manifest, bytes memory data) internal {\n        bytes memory params = abi.encode(nef, manifest, data);\n        Syscalls.contractCall(CONTRACT_MANAGEMENT, \"update\", params);\n    }\n    \n    /**\n     * @dev Destroy contract\n     */\n    function destroyContract() internal {\n        Syscalls.contractCall(CONTRACT_MANAGEMENT, \"destroy\", \"\");\n    }\n    \n    /**\n     * @dev Get contract by hash\n     */\n    function getContract(address hash) internal view returns (ContractState memory) {\n        bytes memory params = abi.encode(hash);\n        bytes memory result = Syscalls.contractCall(CONTRACT_MANAGEMENT, \"getContract\", params);\n        return abi.decode(result, (ContractState));\n    }\n\n    /**\n     * @dev Get contract by id\n     */\n    function getContractById(int256 id) internal view returns (ContractState memory) {\n        bytes memory params = abi.encode(id);\n        bytes memory result = Syscalls.contractCall(CONTRACT_MANAGEMENT, \"getContractById\", params);\n        return abi.decode(result, (ContractState));\n    }\n    \n    /**\n     * @dev List all contracts\n     */\n    function listContracts() internal view returns (Syscalls.Iterator memory) {\n        // Calls ContractManagement.listContracts() which returns a Neo iterator\n        // of deployed contract hashes.\n        //\n        // Consume it via:\n        //   while (it.next()) { bytes memory hash = it.value(); ... }\n        bytes memory params;\n        bytes memory result = Syscalls.contractCall(CONTRACT_MANAGEMENT, \"listContracts\", params);\n        return abi.decode(result, (Syscalls.Iterator));\n    }\n    \n    /**\n     * @dev Check if contract has method\n     */\n    function hasMethod(address hash, string memory method, uint8 paramCount) \n        internal \n        view \n        returns (bool) \n    {\n        bytes memory params = abi.encode(hash, method, paramCount);\n        bytes memory result = Syscalls.contractCall(CONTRACT_MANAGEMENT, \"hasMethod\", params);\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Check if contract exists\n     */\n    function isContract(address hash) internal view returns (bool) {\n        bytes memory params = abi.encode(hash);\n        bytes memory result = Syscalls.contractCall(CONTRACT_MANAGEMENT, \"isContract\", params);\n        return abi.decode(result, (bool));\n    }\n    \n    /**\n     * @dev Get minimum deployment fee\n     */\n    function getMinimumDeploymentFee() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(CONTRACT_MANAGEMENT, \"getMinimumDeploymentFee\", \"\");\n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Set minimum deployment fee\n     */\n    function setMinimumDeploymentFee(uint256 value) internal {\n        bytes memory params = abi.encode(value);\n        Syscalls.contractCall(CONTRACT_MANAGEMENT, \"setMinimumDeploymentFee\", params);\n    }\n    \n    // ========== Policy Native Contract ==========\n    \n    /**\n     * @dev Get fee per byte\n     */\n    function getFeePerByte() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getFeePerByte\", \"\");\n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Set fee per byte\n     */\n    function setFeePerByte(uint256 value) internal {\n        bytes memory params = abi.encode(value);\n        Syscalls.contractCall(POLICY_CONTRACT, \"setFeePerByte\", params);\n    }\n    \n    /**\n     * @dev Get execution fee factor\n     */\n    function getExecFeeFactor() internal view returns (uint32) {\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getExecFeeFactor\", \"\");\n        return abi.decode(result, (uint32));\n    }\n\n    /**\n     * @dev Get execution fee factor in picoGAS\n     */\n    function getExecPicoFeeFactor() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getExecPicoFeeFactor\", \"\");\n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Set execution fee factor\n     */\n    function setExecFeeFactor(uint32 value) internal {\n        bytes memory params = abi.encode(value);\n        Syscalls.contractCall(POLICY_CONTRACT, \"setExecFeeFactor\", params);\n    }\n    \n    /**\n     * @dev Get storage price\n     */\n    function getStoragePrice() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getStoragePrice\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get milliseconds per block\n     */\n    function getMillisecondsPerBlock() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getMillisecondsPerBlock\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Set milliseconds per block\n     */\n    function setMillisecondsPerBlock(uint256 value) internal {\n        bytes memory params = abi.encode(value);\n        Syscalls.contractCall(POLICY_CONTRACT, \"setMillisecondsPerBlock\", params);\n    }\n\n    /**\n     * @dev Get max valid-until-block increment\n     */\n    function getMaxValidUntilBlockIncrement() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getMaxValidUntilBlockIncrement\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Set max valid-until-block increment\n     */\n    function setMaxValidUntilBlockIncrement(uint256 value) internal {\n        bytes memory params = abi.encode(value);\n        Syscalls.contractCall(POLICY_CONTRACT, \"setMaxValidUntilBlockIncrement\", params);\n    }\n\n    /**\n     * @dev Get max traceable blocks\n     */\n    function getMaxTraceableBlocks() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getMaxTraceableBlocks\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Set max traceable blocks\n     */\n    function setMaxTraceableBlocks(uint256 value) internal {\n        bytes memory params = abi.encode(value);\n        Syscalls.contractCall(POLICY_CONTRACT, \"setMaxTraceableBlocks\", params);\n    }\n\n    /**\n     * @dev Get attribute fee\n     */\n    function getAttributeFee(uint8 attributeType) internal view returns (uint256) {\n        bytes memory params = abi.encode(attributeType);\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getAttributeFee\", params);\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Set attribute fee\n     */\n    function setAttributeFee(uint8 attributeType, uint256 value) internal {\n        bytes memory params = abi.encode(attributeType, value);\n        Syscalls.contractCall(POLICY_CONTRACT, \"setAttributeFee\", params);\n    }\n    \n    /**\n     * @dev Set storage price\n     */\n    function setStoragePrice(uint256 value) internal {\n        bytes memory params = abi.encode(value);\n        Syscalls.contractCall(POLICY_CONTRACT, \"setStoragePrice\", params);\n    }\n    \n    /**\n     * @dev Block account\n     */\n    function blockAccount(address account) internal {\n        bytes memory params = abi.encode(account);\n        Syscalls.contractCall(POLICY_CONTRACT, \"blockAccount\", params);\n    }\n    \n    /**\n     * @dev Unblock account\n     */\n    function unblockAccount(address account) internal {\n        bytes memory params = abi.encode(account);\n        Syscalls.contractCall(POLICY_CONTRACT, \"unblockAccount\", params);\n    }\n    \n    /**\n     * @dev Check if account is blocked\n     */\n    function isBlocked(address account) internal view returns (bool) {\n        bytes memory params = abi.encode(account);\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"isBlocked\", params);\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Get blocked accounts iterator\n     */\n    function getBlockedAccounts() internal view returns (Syscalls.Iterator memory) {\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getBlockedAccounts\", \"\");\n        return abi.decode(result, (Syscalls.Iterator));\n    }\n\n    /**\n     * @dev Recover blocked funds (committee only)\n     */\n    function recoverFund(address account, address token) internal returns (bool) {\n        bytes memory params = abi.encode(account, token);\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"recoverFund\", params);\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Set whitelist fee contract (committee only)\n     */\n    function setWhitelistFeeContract(\n        address contractHash,\n        string memory method,\n        uint8 argCount,\n        uint256 fixedFee\n    ) internal {\n        bytes memory params = abi.encode(contractHash, method, argCount, fixedFee);\n        Syscalls.contractCall(POLICY_CONTRACT, \"setWhitelistFeeContract\", params);\n    }\n\n    /**\n     * @dev Remove whitelist fee contract (committee only)\n     */\n    function removeWhitelistFeeContract(\n        address contractHash,\n        string memory method,\n        uint8 argCount\n    ) internal {\n        bytes memory params = abi.encode(contractHash, method, argCount);\n        Syscalls.contractCall(POLICY_CONTRACT, \"removeWhitelistFeeContract\", params);\n    }\n\n    /**\n     * @dev Get whitelisted fee contracts iterator\n     */\n    function getWhitelistFeeContracts() internal view returns (Syscalls.Iterator memory) {\n        bytes memory result = Syscalls.contractCall(POLICY_CONTRACT, \"getWhitelistFeeContracts\", \"\");\n        return abi.decode(result, (Syscalls.Iterator));\n    }\n    \n    // ========== Oracle Native Contract ==========\n    \n    /**\n     * @dev Request oracle data\n     */\n    function requestOracleData(\n        string memory url,\n        string memory filter,\n        string memory callback,\n        bytes memory userData,\n        uint256 gasForResponse\n    ) internal {\n        bytes memory params = abi.encode(url, filter, callback, userData, gasForResponse);\n        Syscalls.contractCall(ORACLE_CONTRACT, \"request\", params);\n    }\n    \n    /**\n     * @dev Get oracle price\n     */\n    function getOraclePrice() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(ORACLE_CONTRACT, \"getPrice\", \"\");\n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Set oracle price\n     */\n    function setOraclePrice(uint256 price) internal {\n        bytes memory params = abi.encode(price);\n        Syscalls.contractCall(ORACLE_CONTRACT, \"setPrice\", params);\n    }\n\n    /**\n     * @dev Finish oracle response (oracle nodes)\n     */\n    function oracleFinish() internal {\n        Syscalls.contractCall(ORACLE_CONTRACT, \"finish\", \"\");\n    }\n\n    /**\n     * @dev Verify oracle response transaction\n     */\n    function oracleVerify() internal view returns (bool) {\n        bytes memory result = Syscalls.contractCall(ORACLE_CONTRACT, \"verify\", \"\");\n        return abi.decode(result, (bool));\n    }\n    \n    // ========== Role Management Native Contract ==========\n    \n    /**\n     * @dev Designate as role\n     */\n    function designateAsRole(bytes1 role, bytes[] memory publicKeys) internal {\n        bytes memory params = abi.encode(role, publicKeys);\n        Syscalls.contractCall(ROLE_MANAGEMENT, \"designateAsRole\", params);\n    }\n    \n    /**\n     * @dev Get designated by role\n     */\n    function getDesignatedByRole(bytes1 role, uint256 index) internal view returns (bytes[] memory) {\n        bytes memory params = abi.encode(role, index);\n        bytes memory result = Syscalls.contractCall(ROLE_MANAGEMENT, \"getDesignatedByRole\", params);\n        return abi.decode(result, (bytes[]));\n    }\n\n    // ========== Ledger Native Contract ==========\n\n    /**\n     * @dev Get current block index\n     */\n    function currentIndex() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"currentIndex\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get current block hash\n     */\n    function currentHash() internal view returns (bytes32) {\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"currentHash\", \"\");\n        return abi.decode(result, (bytes32));\n    }\n\n    /**\n     * @dev Get block by index\n     */\n    function getBlock(uint256 index) internal view returns (Syscalls.Block memory) {\n        bytes memory params = abi.encode(index);\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"getBlock\", params);\n        return abi.decode(result, (Syscalls.Block));\n    }\n\n    /**\n     * @dev Get block by hash\n     */\n    function getBlock(bytes32 hash) internal view returns (Syscalls.Block memory) {\n        bytes memory params = abi.encode(hash);\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"getBlock\", params);\n        return abi.decode(result, (Syscalls.Block));\n    }\n\n    /**\n     * @dev Get transaction by hash\n     */\n    function getTransaction(bytes32 hash) internal view returns (Syscalls.Transaction memory) {\n        bytes memory params = abi.encode(hash);\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"getTransaction\", params);\n        return abi.decode(result, (Syscalls.Transaction));\n    }\n\n    /**\n     * @dev Get transaction height\n     */\n    function getTransactionHeight(bytes32 hash) internal view returns (int256) {\n        bytes memory params = abi.encode(hash);\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"getTransactionHeight\", params);\n        return abi.decode(result, (int256));\n    }\n\n    /**\n     * @dev Get transaction from block\n     */\n    function getTransactionFromBlock(uint256 blockIndex, uint256 txIndex)\n        internal\n        view\n        returns (Syscalls.Transaction memory)\n    {\n        bytes memory params = abi.encode(blockIndex, txIndex);\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"getTransactionFromBlock\", params);\n        return abi.decode(result, (Syscalls.Transaction));\n    }\n\n    /**\n     * @dev Get transaction from block by hash\n     */\n    function getTransactionFromBlock(bytes32 blockHash, uint256 txIndex)\n        internal\n        view\n        returns (Syscalls.Transaction memory)\n    {\n        bytes memory params = abi.encode(blockHash, txIndex);\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"getTransactionFromBlock\", params);\n        return abi.decode(result, (Syscalls.Transaction));\n    }\n\n    /**\n     * @dev Get transaction signers\n     */\n    function getTransactionSigners(bytes32 hash) internal view returns (Syscalls.Signer[] memory) {\n        bytes memory params = abi.encode(hash);\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"getTransactionSigners\", params);\n        return abi.decode(result, (Syscalls.Signer[]));\n    }\n\n    /**\n     * @dev Get transaction VM state\n     */\n    function getTransactionVMState(bytes32 hash) internal view returns (uint8) {\n        bytes memory params = abi.encode(hash);\n        bytes memory result = Syscalls.contractCall(LEDGER_CONTRACT, \"getTransactionVMState\", params);\n        return abi.decode(result, (uint8));\n    }\n\n    // ========== Notary Native Contract ==========\n\n    /**\n     * @dev Verify notary-assisted transaction\n     */\n    function notaryVerify(bytes memory signature) internal view returns (bool) {\n        bytes memory params = abi.encode(signature);\n        bytes memory result = Syscalls.contractCall(NOTARY_CONTRACT, \"verify\", params);\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Get notary deposit balance\n     */\n    function notaryBalanceOf(address account) internal view returns (uint256) {\n        bytes memory params = abi.encode(account);\n        bytes memory result = Syscalls.contractCall(NOTARY_CONTRACT, \"balanceOf\", params);\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get notary deposit expiration height\n     */\n    function notaryExpirationOf(address account) internal view returns (uint256) {\n        bytes memory params = abi.encode(account);\n        bytes memory result = Syscalls.contractCall(NOTARY_CONTRACT, \"expirationOf\", params);\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Lock notary deposit until a specific block height\n     */\n    function notaryLockDepositUntil(address account, uint256 till) internal returns (bool) {\n        bytes memory params = abi.encode(account, till);\n        bytes memory result = Syscalls.contractCall(NOTARY_CONTRACT, \"lockDepositUntil\", params);\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Withdraw notary deposit\n     */\n    function notaryWithdraw(address from, address to) internal returns (bool) {\n        bytes memory params = abi.encode(from, to);\n        bytes memory result = Syscalls.contractCall(NOTARY_CONTRACT, \"withdraw\", params);\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Get maximum NotValidBefore delta\n     */\n    function notaryGetMaxNotValidBeforeDelta() internal view returns (uint256) {\n        bytes memory result = Syscalls.contractCall(NOTARY_CONTRACT, \"getMaxNotValidBeforeDelta\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Set maximum NotValidBefore delta\n     */\n    function notarySetMaxNotValidBeforeDelta(uint256 value) internal {\n        bytes memory params = abi.encode(value);\n        Syscalls.contractCall(NOTARY_CONTRACT, \"setMaxNotValidBeforeDelta\", params);\n    }\n\n    /**\n     * @dev Handle NEP-17 payment (notary deposit)\n     */\n    function notaryOnNEP17Payment(address from, uint256 amount, bytes memory data) internal {\n        bytes memory params = abi.encode(from, amount, data);\n        Syscalls.contractCall(NOTARY_CONTRACT, \"onNEP17Payment\", params);\n    }\n\n    // ========== Treasury Native Contract ==========\n\n    /**\n     * @dev Verify treasury transaction\n     */\n    function treasuryVerify() internal view returns (bool) {\n        bytes memory result = Syscalls.contractCall(TREASURY_CONTRACT, \"verify\", \"\");\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Handle NEP-17 payment\n     */\n    function treasuryOnNEP17Payment(address from, uint256 amount, bytes memory data) internal {\n        bytes memory params = abi.encode(from, amount, data);\n        Syscalls.contractCall(TREASURY_CONTRACT, \"onNEP17Payment\", params);\n    }\n\n    /**\n     * @dev Handle NEP-11 payment\n     */\n    function treasuryOnNEP11Payment(\n        address from,\n        uint256 amount,\n        bytes memory tokenId,\n        bytes memory data\n    ) internal {\n        bytes memory params = abi.encode(from, amount, tokenId, data);\n        Syscalls.contractCall(TREASURY_CONTRACT, \"onNEP11Payment\", params);\n    }\n\n    // ========== Data Structures ==========\n    \n    struct NeoCandidate {\n        bytes publicKey;\n        uint256 votes;\n    }\n    \n    struct AccountState {\n        // NeoToken NeoAccountState:\n        // [balance, balanceHeight, voteTo (ECPoint bytes or null), lastGasPerVote]\n        uint256 balance;\n        uint256 balanceHeight;\n        bytes voteTo;\n        uint256 lastGasPerVote;\n    }\n    \n    struct ContractState {\n        address hash;\n        bytes nef;\n        bytes manifest;\n        uint256 updateCounter;\n    }\n\n    struct WhitelistedContract {\n        address contractHash;\n        string method;\n        uint256 argCount;\n        int256 fixedFee;\n    }\n    \n    // ========== Helper Functions ==========\n    \n    /**\n     * @dev Check if native contract exists\n     */\n    function isNativeContract(address contractHash) internal pure returns (bool) {\n        return contractHash == NEO_CONTRACT ||\n               contractHash == GAS_CONTRACT ||\n               contractHash == CONTRACT_MANAGEMENT ||\n               contractHash == POLICY_CONTRACT ||\n               contractHash == ORACLE_CONTRACT ||\n               contractHash == ROLE_MANAGEMENT ||\n               contractHash == NOTARY_CONTRACT ||\n               contractHash == TREASURY_CONTRACT ||\n               contractHash == LEDGER_CONTRACT ||\n               contractHash == CRYPTO_LIB ||\n               contractHash == STD_LIB;\n    }\n    \n    /**\n     * @dev Get native contract name\n     */\n    function getNativeContractName(address contractHash) internal pure returns (string memory) {\n        if (contractHash == NEO_CONTRACT) return \"NeoToken\";\n        if (contractHash == GAS_CONTRACT) return \"GasToken\";\n        if (contractHash == CONTRACT_MANAGEMENT) return \"ContractManagement\";\n        if (contractHash == POLICY_CONTRACT) return \"PolicyContract\";\n        if (contractHash == ORACLE_CONTRACT) return \"OracleContract\";\n        if (contractHash == ROLE_MANAGEMENT) return \"RoleManagement\";\n        if (contractHash == NOTARY_CONTRACT) return \"Notary\";\n        if (contractHash == TREASURY_CONTRACT) return \"Treasury\";\n        if (contractHash == LEDGER_CONTRACT) return \"LedgerContract\";\n        if (contractHash == CRYPTO_LIB) return \"CryptoLib\";\n        if (contractHash == STD_LIB) return \"StdLib\";\n        return \"Unknown\";\n    }\n    \n    /**\n     * @dev Get all native contract addresses\n     */\n    function getAllNativeContracts() internal pure returns (address[] memory) {\n        address[] memory contracts = new address[](11);\n        contracts[0] = NEO_CONTRACT;\n        contracts[1] = GAS_CONTRACT;\n        contracts[2] = CONTRACT_MANAGEMENT;\n        contracts[3] = POLICY_CONTRACT;\n        contracts[4] = ORACLE_CONTRACT;\n        contracts[5] = ROLE_MANAGEMENT;\n        contracts[6] = NOTARY_CONTRACT;\n        contracts[7] = TREASURY_CONTRACT;\n        contracts[8] = LEDGER_CONTRACT;\n        contracts[9] = CRYPTO_LIB;\n        contracts[10] = STD_LIB;\n        return contracts;\n    }\n    \n    /**\n     * @dev Estimate gas for native contract call\n     */\n    function estimateNativeCallGas(\n        address contractHash,\n        string memory method,\n        bytes memory params\n    ) internal view returns (uint256) {\n        // Base gas cost for native contract calls\n        uint256 baseGas = 1000000; // 0.01 GAS\n        \n        // Additional gas based on method complexity\n        if (contractHash == NEO_CONTRACT) {\n            if (keccak256(bytes(method)) == keccak256(\"vote\")) return baseGas * 100;\n            if (keccak256(bytes(method)) == keccak256(\"registerCandidate\")) return baseGas * 1000;\n        }\n        \n        if (contractHash == CONTRACT_MANAGEMENT) {\n            if (keccak256(bytes(method)) == keccak256(\"deploy\")) return baseGas * 500;\n            if (keccak256(bytes(method)) == keccak256(\"update\")) return baseGas * 300;\n        }\n        \n        if (contractHash == ORACLE_CONTRACT) {\n            if (keccak256(bytes(method)) == keccak256(\"request\")) return baseGas * 50;\n        }\n        \n        return baseGas;\n    }\n    \n    /**\n     * @dev Batch native contract calls\n     */\n    function batchNativeCalls(\n        address[] memory /*contracts*/,\n        string[] memory /*methods*/,\n        bytes[] memory /*params*/\n    ) internal pure returns (bytes[] memory /*results*/) {\n        revert(\n            \"NativeCalls: batchNativeCalls is disabled in strict-manifest mode; call explicit native wrappers\"\n        );\n    }\n    \n    /**\n     * @dev Get network configuration\n     */\n    function getNetworkConfiguration() internal view returns (NetworkConfig memory) {\n        return NetworkConfig({\n            feePerByte: getFeePerByte(),\n            execFeeFactor: getExecFeeFactor(),\n            storagePrice: getStoragePrice(),\n            gasPerBlock: getGasPerBlock(),\n            oraclePrice: getOraclePrice(),\n            minimumDeploymentFee: getMinimumDeploymentFee()\n        });\n    }\n    \n    struct NetworkConfig {\n        uint256 feePerByte;\n        uint32 execFeeFactor;\n        uint256 storagePrice;\n        uint256 gasPerBlock;\n        uint256 oraclePrice;\n        uint256 minimumDeploymentFee;\n    }\n    \n    // ========== Governance Functions ==========\n    \n    /**\n     * @dev Get committee members\n     */\n    function getCommittee() internal view returns (bytes[] memory) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"getCommittee\", \"\");\n        return abi.decode(result, (bytes[]));\n    }\n\n    /**\n     * @dev Get committee multi-sig address\n     */\n    function getCommitteeAddress() internal view returns (address) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"getCommitteeAddress\", \"\");\n        return abi.decode(result, (address));\n    }\n    \n    /**\n     * @dev Get next block validators\n     */\n    function getNextBlockValidators() internal view returns (address[] memory) {\n        bytes memory result = Syscalls.contractCall(NEO_CONTRACT, \"getNextBlockValidators\", \"\");\n        return abi.decode(result, (address[]));\n    }\n    \n    /**\n     * @dev Check if address is committee member\n     */\n    function isCommittee(address account) internal view returns (bool) {\n        // Delegate to committee address check - verifies if account\n        // matches the committee multi-sig address\n        address committeeAddr = getCommitteeAddress();\n        if (account == committeeAddr) return true;\n        // For individual member check, use witness verification\n        return false;\n    }\n    \n    /**\n     * @dev Check if address is validator\n     */\n    function isValidator(address account) internal view returns (bool) {\n        address[] memory validators = getNextBlockValidators();\n        for (uint256 i = 0; i < validators.length; i++) {\n            if (validators[i] == account) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    // ========== Native Contract Utilities ==========\n    \n    /**\n     * @dev Get native contract manifest\n     */\n    function getNativeContractManifest(address contractHash) internal view returns (bytes memory) {\n        ContractState memory state = getContract(contractHash);\n        return state.manifest;\n    }\n    \n    /**\n     * @dev Safe native contract call with error handling\n     */\n    function safeNativeCall(\n        address /*contractHash*/,\n        string memory /*method*/,\n        bytes memory /*params*/\n    ) internal pure returns (bool success, bytes memory result) {\n        return (false, \"\");\n    }\n    \n    /**\n     * @dev External wrapper for try/catch\n     */\n    function externalNativeCall(\n        address /*contractHash*/,\n        string calldata /*method*/,\n        bytes calldata /*params*/\n    ) external pure returns (bytes memory) {\n        revert(\"NativeCalls: externalNativeCall disabled in strict-manifest mode\");\n    }\n}\n"
    },
    "contracts/NativeContracts.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title Neo N3 Native Contract Addresses\n * @dev Canonical script hash constants for Neo N3 native contracts and core libraries.\n *\n * These addresses are deterministic and identical on all Neo N3 networks\n * (MainNet/TestNet/private networks).\n *\n * NOTE: These are written in Neo RPC-style big-endian hex (same values you\n * see via RPC/explorer). The compiler lowers `address` literals to NeoVM\n * `Hash160` stack representation as needed.\n */\nlibrary NativeContracts {\n    address constant NEO_CONTRACT = 0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5;\n    address constant GAS_CONTRACT = 0xd2a4cff31913016155e38e474a2c06d08be276cf;\n    address constant CONTRACT_MANAGEMENT = 0xfffdc93764dbaddd97c48f252a53ea4643faa3fd;\n    address constant POLICY_CONTRACT = 0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b;\n    address constant ORACLE_CONTRACT = 0xfe924b7cfe89ddd271abaf7210a80a7e11178758;\n    address constant ROLE_MANAGEMENT = 0x49cf4e5378ffcd4dec034fd98a174c5491e395e2;\n    address constant NOTARY_CONTRACT = 0xc1e14f19c3e60d0b9244d06dd7ba9b113135ec3b;\n    address constant TREASURY_CONTRACT = 0x156326f25b1b5d839a4d326aeaa75383c9563ac1;\n    address constant LEDGER_CONTRACT = 0xda65b600f7124ce6c79950c1772a36403104f2be;\n    address constant CRYPTO_LIB = 0x726cb6e0cd8628a1350a611384688911ab75f51b;\n    address constant STD_LIB = 0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0;\n}\n"
    },
    "contracts/NeoBytes.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title NeoBytes\n * @dev Byte parsing helpers for NeoVM-oriented ABI/data bridge handling.\n */\nabstract contract NeoBytes {\n    /**\n     * @dev Check whether every item is exactly 1 byte.\n     */\n    function nbAllSingleByteItems(bytes[] calldata items) internal pure returns (bool) {\n        for (uint256 i = 0; i < items.length; i++) {\n            if (items[i].length != 1) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Flatten an array of byte slices into one contiguous buffer.\n     */\n    function nbFlattenItems(bytes[] calldata items) internal pure returns (bytes memory out) {\n        uint256 total = 0;\n        for (uint256 i = 0; i < items.length; i++) {\n            total += items[i].length;\n        }\n\n        out = new bytes(total);\n        uint256 offset = 0;\n        for (uint256 i = 0; i < items.length; i++) {\n            bytes calldata item = items[i];\n            for (uint256 j = 0; j < item.length; j++) {\n                out[offset++] = item[j];\n            }\n        }\n    }\n\n    /**\n     * @dev Read a 32-byte unsigned integer from big-endian memory bytes at `start`.\n     */\n    function nbBytesToUintBE(bytes memory raw, uint256 start) internal pure returns (uint256 value) {\n        if (start + 32 > raw.length) {\n            return 0;\n        }\n\n        for (uint256 i = 0; i < 32; i++) {\n            value = (value << 8) | uint256(uint8(raw[start + i]));\n        }\n    }\n\n    /**\n     * @dev Decode UTF-8 string slice from bytes range.\n     */\n    function nbBytesToString(bytes memory raw, uint256 start, uint256 len) internal pure returns (string memory) {\n        if (start + len > raw.length) {\n            return \"\";\n        }\n\n        bytes memory out = new bytes(len);\n        for (uint256 i = 0; i < len; i++) {\n            out[i] = raw[start + i];\n        }\n        return string(out);\n    }\n\n    /**\n     * @dev Decode little-endian uint from memory bytes (up to 32 bytes).\n     */\n    function nbBytesToUintLE(bytes memory raw) internal pure returns (uint256 value) {\n        uint256 len = raw.length;\n        if (len > 32) {\n            len = 32;\n        }\n\n        for (uint256 i = 0; i < len; i++) {\n            value |= uint256(uint8(raw[i])) << (8 * i);\n        }\n    }\n\n    /**\n     * @dev Decode little-endian uint from calldata bytes (up to 32 bytes).\n     */\n    function nbBytesToUintLE(bytes calldata raw) internal pure returns (uint256 value) {\n        uint256 len = raw.length;\n        if (len > 32) {\n            len = 32;\n        }\n\n        for (uint256 i = 0; i < len; i++) {\n            value |= uint256(uint8(raw[i])) << (8 * i);\n        }\n    }\n}\n"
    },
    "contracts/NeoMath.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title NeoMath\n * @dev Math helpers for NeoVM-compatible contracts.\n */\nabstract contract NeoMath {\n    /**\n     * @dev Ceiling division with denominator validation.\n     */\n    function nmCeilingDiv(uint256 numerator, uint256 denominator) internal pure returns (uint256) {\n        require(denominator > 0, \"invalid denominator\");\n        if (numerator == 0) {\n            return 0;\n        }\n        return (numerator + denominator - 1) / denominator;\n    }\n\n    /**\n     * @dev Multiply and clamp to NeoVM Integer max (2^255-1).\n     */\n    function nmMulClampMax(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 nmNeoIntMax = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n        if (a == 0 || b == 0) {\n            return 0;\n        }\n        if (a > nmNeoIntMax / b) {\n            return nmNeoIntMax;\n        }\n        return a * b;\n    }\n}\n"
    },
    "contracts/NEP17Rescue.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title NEP17Rescue\n * @dev Optional extension for NEP-17 tokens to recover accidentally sent native tokens.\n *\n * IMPORTANT: In strict-manifest mode this rescue is limited to the two native\n * Neo N3 tokens (GAS and NEO) because recovering arbitrary NEP-17 tokens would\n * require a dynamic `Syscalls.contractCall` to an unknown contract hash, which\n * forces wildcard contract permissions in the manifest.\n *\n * If you need to rescue arbitrary NEP-17 tokens, use `Syscalls.contractCall`\n * directly and accept the wildcard-contract permission trade-off (or supply\n * explicit `--manifest-permissions` overrides at compile time).\n *\n * If you don't need token rescue functionality, inherit `NEP17` directly.\n */\n\nimport \"../standards/NEP17.sol\";\nimport \"./NativeCalls.sol\";\n\nabstract contract NEP17Rescue is NEP17 {\n    function emergencyTokenRecovery(\n        address token,\n        address to,\n        uint256 amount,\n        bytes calldata data\n    ) external onlyOwner {\n        require(token != address(this), \"NEP17: cannot recover own tokens\");\n        require(to != address(0), \"NEP17: cannot recover to zero address\");\n\n        bool ok;\n        if (token == NativeCalls.GAS_CONTRACT) {\n            ok = NativeCalls.gasTransfer(address(this), to, amount, data);\n        } else if (token == NativeCalls.NEO_CONTRACT) {\n            ok = NativeCalls.neoTransfer(address(this), to, amount, data);\n        } else {\n            revert(\"NEP17: strict rescue supports NEO/GAS only\");\n        }\n\n        require(ok, \"NEP17: token recovery failed\");\n    }\n}\n\n"
    },
    "contracts/OracleService.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title OracleService\n * @dev Convenience wrapper around the Neo N3 Oracle native contract.\n *\n * This is NOT a NEP standard. Neo N3 provides oracle functionality via the\n * native `Oracle` contract. The `Syscalls.oracleRequest(...)` intrinsic lowers\n * to `Oracle.request(...)`.\n *\n * The Oracle native contract calls back into the requesting contract using the\n * provided callback method name, with the signature:\n *\n *   callback(string url, bytes userData, int code, bytes result)\n *\n * This helper:\n * - Sends requests to the native oracle contract\n * - Receives the native callback (`oracleCallback`)\n * - Forwards responses to the original requester via a FIXED callback method\n *   (`onOracleResponse`) to avoid full-wildcard manifest permissions\n */\n\nimport \"./FrameworkBase.sol\";\nimport \"./Syscalls.sol\";\nimport \"../libraries/Runtime.sol\";\n\n/**\n * @dev Requester callback interface.\n *\n * The method name is fixed so that manifest inference can restrict permissions\n * to `methods:[\"onOracleResponse\"]` rather than `methods:\"*\"`.\n */\ninterface IOracleServiceReceiver {\n    function onOracleResponse(\n        uint256 requestId,\n        uint256 code,\n        bytes calldata result,\n        bytes calldata userData\n    ) external;\n}\n\ncontract OracleService is FrameworkBase {\n    using Runtime for *;\n\n    // Oracle native contract hash (UInt160 as Solidity address).\n    // Little-endian UInt160: 0x588717117e0aa81072afab71d2dd89fe7c4b92fe\n    // Big-endian (Neo RPC):  0xfe924b7cfe89ddd271abaf7210a80a7e11178758\n    address private constant ORACLE_CONTRACT = 0xfe924b7cfe89ddd271abaf7210a80a7e11178758;\n\n    // Callback method invoked by the Oracle native contract on this service.\n    string private constant ORACLE_NATIVE_CALLBACK = \"oracleCallback\";\n\n    struct Request {\n        address requester;\n        string url;\n        string filter;\n        bytes userData;\n        uint256 gasForResponse;\n        uint256 timestamp;\n        bool completed;\n        uint256 responseCode;\n        bytes responseResult;\n    }\n\n    uint256 private _nextRequestId = 1;\n    mapping(uint256 => Request) private _requests;\n\n    event OracleRequest(uint256 indexed requestId, address indexed requester, string url, string filter);\n    event OracleResponse(uint256 indexed requestId, address indexed requester, uint256 code, bytes result);\n    event OracleForwardFailed(uint256 indexed requestId, address indexed requester);\n\n    error OracleUnauthorizedSender(address caller);\n    error OracleRequestNotFound(uint256 requestId);\n\n    modifier onlyOracleNative() {\n        if (msg.sender != ORACLE_CONTRACT) revert OracleUnauthorizedSender(msg.sender);\n        _;\n    }\n\n    /**\n     * @dev Issue an oracle request via the Oracle native contract.\n     *\n     * The `userData` provided here is stored and forwarded back to the requester\n     * in `onOracleResponse`.\n     */\n    function request(\n        string calldata url,\n        string calldata filter,\n        bytes calldata userData,\n        uint256 gasForResponse\n    ) external returns (uint256 requestId) {\n        requestId = _nextRequestId++;\n\n        _requests[requestId] = Request({\n            requester: msg.sender,\n            url: url,\n            filter: filter,\n            userData: userData,\n            gasForResponse: gasForResponse,\n            timestamp: block.timestamp,\n            completed: false,\n            responseCode: 0,\n            responseResult: \"\"\n        });\n\n        // Encode our internal request id into the oracle userData so we can\n        // correlate the native callback with this request.\n        bytes memory oracleUserData = abi.encode(requestId);\n\n        Syscalls.oracleRequest(url, filter, ORACLE_NATIVE_CALLBACK, oracleUserData, gasForResponse);\n\n        emit OracleRequest(requestId, msg.sender, url, filter);\n    }\n\n    function getRequest(uint256 requestId) external view returns (Request memory) {\n        Request memory req = _requests[requestId];\n        if (req.requester == address(0)) revert OracleRequestNotFound(requestId);\n        return req;\n    }\n\n    /**\n     * @dev Callback invoked by the Oracle native contract.\n     *\n     * Neo N3 signature: callback(string url, any userData, int code, bytes result)\n     */\n    function oracleCallback(\n        string calldata url,\n        bytes calldata userData,\n        uint256 code,\n        bytes calldata result\n    ) external onlyOracleNative {\n        uint256 requestId = abi.decode(userData, (uint256));\n\n        Request storage req = _requests[requestId];\n        if (req.requester == address(0)) revert OracleRequestNotFound(requestId);\n        if (req.completed) {\n            // Idempotency guard: ignore duplicate/replayed callbacks.\n            return;\n        }\n\n        // Best-effort sanity check: ensure url matches the request record.\n        // This avoids accidentally correlating two different requests if userData collides.\n        if (keccak256(bytes(req.url)) != keccak256(bytes(url))) {\n            // Keep going; the response will still be recorded under `requestId`.\n        }\n\n        req.completed = true;\n        req.responseCode = code;\n        req.responseResult = result;\n\n        emit OracleResponse(requestId, req.requester, code, result);\n\n        // Forward to requester (best-effort).\n        // Use a typed local variable so the compiler can treat this as an external call target.\n        address requester = req.requester;\n        if (requester.code.length > 0) {\n            try IOracleServiceReceiver(requester).onOracleResponse(\n                requestId,\n                code,\n                result,\n                req.userData\n            ) {\n                // ok\n            } catch {\n                emit OracleForwardFailed(requestId, requester);\n            }\n        }\n    }\n}\n"
    },
    "contracts/Syscalls.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title Neo N3 System Calls\n * @dev Complete mapping of Neo N3 syscalls to Solidity functions\n * @author Jimmy <jimmy@r3e.network>\n * \n * This library provides direct access to all Neo N3 system calls,\n * enabling Solidity contracts to fully utilize Neo blockchain features.\n *\n * NOTE: Neo N3 exposes many features via *native contracts* (Ledger, Policy,\n * Oracle, ContractManagement, etc.) rather than syscalls. The neo-devpack-solidity\n * compiler lowers these helpers to `System.Contract.Call` as needed.\n */\n\nlibrary Syscalls {\n\n    // Native contract script hashes (deterministic, identical on all Neo N3 networks)\n    address constant CONTRACT_MANAGEMENT = 0xfffdc93764dbaddd97c48f252a53ea4643faa3fd;\n    address constant POLICY_CONTRACT = 0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b;\n    address constant ORACLE_CONTRACT = 0xfe924b7cfe89ddd271abaf7210a80a7e11178758;\n    address constant ROLE_MANAGEMENT = 0x49cf4e5378ffcd4dec034fd98a174c5491e395e2;\n    address constant LEDGER_CONTRACT = 0xda65b600f7124ce6c79950c1772a36403104f2be;\n    address constant CRYPTO_LIB = 0x726cb6e0cd8628a1350a611384688911ab75f51b;\n    address constant STD_LIB = 0xacce6fd80d44e1796aa0c2c625e9e4e0ce39efc0;\n    \n    // ========== Blockchain System Calls ==========\n    \n    /**\n     * @dev Get current block index\n     */\n    function getCurrentIndex() internal view returns (uint256) {\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"currentIndex\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get current block hash\n     */\n    function getCurrentHash() internal view returns (bytes32) {\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"currentHash\", \"\");\n        return abi.decode(result, (bytes32));\n    }\n    \n    /**\n     * @dev Get block by index\n     */\n    function getBlock(uint256 index) internal view returns (Block memory) {\n        bytes memory data = abi.encode(index);\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"getBlock\", data);\n        return abi.decode(result, (Block));\n    }\n\n    /**\n     * @dev Get block by hash\n     */\n    function getBlock(bytes32 hash) internal view returns (Block memory) {\n        bytes memory data = abi.encode(hash);\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"getBlock\", data);\n        return abi.decode(result, (Block));\n    }\n    \n    /**\n     * @dev Get transaction by hash\n     */\n    function getTransaction(bytes32 hash) internal view returns (Transaction memory) {\n        bytes memory data = abi.encode(hash);\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"getTransaction\", data);\n        return abi.decode(result, (Transaction));\n    }\n    \n    /**\n     * @dev Get transaction height\n     */\n    function getTransactionHeight(bytes32 hash) internal view returns (int256) {\n        bytes memory data = abi.encode(hash);\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"getTransactionHeight\", data);\n        return abi.decode(result, (int256));\n    }\n    \n    /**\n     * @dev Get transaction from block\n     */\n    function getTransactionFromBlock(uint256 blockIndex, uint256 txIndex) \n        internal \n        view \n        returns (Transaction memory) \n    {\n        bytes memory data = abi.encode(blockIndex, txIndex);\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"getTransactionFromBlock\", data);\n        return abi.decode(result, (Transaction));\n    }\n\n    /**\n     * @dev Get transaction from block by hash\n     */\n    function getTransactionFromBlock(bytes32 blockHash, uint256 txIndex)\n        internal\n        view\n        returns (Transaction memory)\n    {\n        bytes memory data = abi.encode(blockHash, txIndex);\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"getTransactionFromBlock\", data);\n        return abi.decode(result, (Transaction));\n    }\n\n    /**\n     * @dev Get transaction signers\n     */\n    function getTransactionSigners(bytes32 hash) internal view returns (Signer[] memory) {\n        bytes memory data = abi.encode(hash);\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"getTransactionSigners\", data);\n        return abi.decode(result, (Signer[]));\n    }\n\n    /**\n     * @dev Get transaction VM state\n     */\n    function getTransactionVMState(bytes32 hash) internal view returns (uint8) {\n        bytes memory data = abi.encode(hash);\n        bytes memory result = contractCall(LEDGER_CONTRACT, \"getTransactionVMState\", data);\n        return abi.decode(result, (uint8));\n    }\n    \n    // ========== Contract System Calls ==========\n    \n    /**\n     * @dev Call another contract\n     */\n    function contractCall(\n        address scriptHash,\n        string memory method,\n        bytes memory params\n    ) internal returns (bytes memory) {\n        bytes memory data = abi.encode(scriptHash, method, params);\n        return _syscallBytes(\"System.Contract.Call\", data);\n    }\n    \n    /**\n     * @dev Call contract with flags\n     * @notice Neo N3 does not have System.Contract.CallEx. The flags parameter is\n     *         accepted for API compatibility but currently has no effect.\n     * @param scriptHash The target contract script hash\n     * @param method The method name to call\n     * @param params The encoded parameters\n     * @param flags Call flags (currently ignored - reserved for future use)\n     * @return The result of the contract call\n     */\n    function contractCallWithFlags(\n        address scriptHash,\n        string memory method,\n        bytes memory params,\n        uint8 flags\n    ) internal returns (bytes memory) {\n        // Flags parameter is reserved for future use when Neo N3 adds CallEx support\n        // Currently ignored - passed in data for forward compatibility\n        bytes memory data = abi.encode(scriptHash, method, params, flags);\n        return _syscallBytes(\"System.Contract.Call\", data);\n    }\n\n    /**\n     * @dev Get current call flags\n     */\n    function getCallFlags() internal view returns (uint8) {\n        return uint8(_syscall(\"System.Contract.GetCallFlags\", \"\"));\n    }\n\n    /**\n     * @dev Create a standard signature account script hash from an ECPoint public key.\n     *\n     * Syscall: System.Contract.CreateStandardAccount(pubkey: ByteString) -> UInt160\n     */\n    function createStandardAccount(bytes memory publicKey) internal view returns (address) {\n        bytes memory data = abi.encode(publicKey);\n        bytes memory result = _syscallBytes(\"System.Contract.CreateStandardAccount\", data);\n        return abi.decode(result, (address));\n    }\n\n    /**\n     * @dev Create a multisig account script hash from ECPoint public keys.\n     *\n     * Syscall: System.Contract.CreateMultisigAccount(m: int, pubkeys: Array) -> UInt160\n     */\n    function createMultisigAccount(uint256 m, bytes[] memory publicKeys) internal view returns (address) {\n        bytes memory data = abi.encode(m, publicKeys);\n        bytes memory result = _syscallBytes(\"System.Contract.CreateMultisigAccount\", data);\n        return abi.decode(result, (address));\n    }\n    \n    /**\n     * @dev Create new contract\n     */\n    function contractCreate(bytes memory nef, bytes memory manifest) internal returns (address) {\n        bytes memory data = abi.encode(nef, manifest);\n        bytes memory result = contractCall(CONTRACT_MANAGEMENT, \"deploy\", data);\n        ContractStateNative memory state = abi.decode(result, (ContractStateNative));\n        return state.hash;\n    }\n\n    /**\n     * @dev Create new contract and pass deployment data to `_deploy(data, false)`\n     */\n    function contractCreate(bytes memory nef, bytes memory manifest, bytes memory deployData)\n        internal\n        returns (address)\n    {\n        bytes memory data = abi.encode(nef, manifest, deployData);\n        bytes memory result = contractCall(CONTRACT_MANAGEMENT, \"deploy\", data);\n        ContractStateNative memory state = abi.decode(result, (ContractStateNative));\n        return state.hash;\n    }\n    \n    /**\n     * @dev Update contract\n     */\n    function contractUpdate(bytes memory nef, bytes memory manifest) internal {\n        bytes memory data = abi.encode(nef, manifest);\n        contractCall(CONTRACT_MANAGEMENT, \"update\", data);\n    }\n\n    /**\n     * @dev Update contract and pass update data to `_deploy(data, true)`\n     */\n    function contractUpdate(bytes memory nef, bytes memory manifest, bytes memory updateData) internal {\n        bytes memory data = abi.encode(nef, manifest, updateData);\n        contractCall(CONTRACT_MANAGEMENT, \"update\", data);\n    }\n    \n    /**\n     * @dev Destroy contract\n     */\n    function contractDestroy() internal {\n        contractCall(CONTRACT_MANAGEMENT, \"destroy\", \"\");\n    }\n    \n    /**\n     * @dev Get executing script hash\n     */\n    function getExecutingScriptHash() internal view returns (address) {\n        bytes memory result = _syscallBytes(\"System.Runtime.GetExecutingScriptHash\", \"\");\n        return abi.decode(result, (address));\n    }\n    \n    /**\n     * @dev Get calling script hash\n     */\n    function getCallingScriptHash() internal view returns (address) {\n        bytes memory result = _syscallBytes(\"System.Runtime.GetCallingScriptHash\", \"\");\n        return abi.decode(result, (address));\n    }\n    \n    /**\n     * @dev Get entry script hash\n     */\n    function getEntryScriptHash() internal view returns (address) {\n        bytes memory result = _syscallBytes(\"System.Runtime.GetEntryScriptHash\", \"\");\n        return abi.decode(result, (address));\n    }\n\n    /**\n     * @dev Get script container\n     */\n    function getScriptContainer() internal view returns (Transaction memory) {\n        bytes memory result = _syscallBytes(\"System.Runtime.GetScriptContainer\", \"\");\n        return abi.decode(result, (Transaction));\n    }\n\n    /**\n     * @dev Load script with arguments\n     */\n    function loadScript(bytes memory script, uint8 callFlags, bytes[] memory args) internal {\n        bytes memory data = abi.encode(script, callFlags, args);\n        _syscallVoid(\"System.Runtime.LoadScript\", data);\n    }\n    \n    // ========== Storage System Calls ==========\n    \n    /**\n     * @dev Get storage context\n     */\n    function getStorageContext() internal view returns (StorageContext memory) {\n        bytes memory result = _syscallBytes(\"System.Storage.GetContext\", \"\");\n        return abi.decode(result, (StorageContext));\n    }\n    \n    /**\n     * @dev Get read-only storage context\n     */\n    function getReadOnlyStorageContext() internal view returns (StorageContext memory) {\n        bytes memory result = _syscallBytes(\"System.Storage.GetReadOnlyContext\", \"\");\n        return abi.decode(result, (StorageContext));\n    }\n\n    /**\n     * @dev Convert storage context to read-only\n     */\n    function storageAsReadOnly(StorageContext memory context) internal view returns (StorageContext memory) {\n        bytes memory data = abi.encode(context);\n        bytes memory result = _syscallBytes(\"System.Storage.AsReadOnly\", data);\n        return abi.decode(result, (StorageContext));\n    }\n    \n    /**\n     * @dev Storage get\n     */\n    function storageGet(StorageContext memory context, bytes memory key) \n        internal \n        view \n        returns (bytes memory) \n    {\n        bytes memory data = abi.encode(context, key);\n        return _syscallBytes(\"System.Storage.Get\", data);\n    }\n    \n    /**\n     * @dev Storage put\n     */\n    function storagePut(StorageContext memory context, bytes memory key, bytes memory value) internal {\n        bytes memory data = abi.encode(context, key, value);\n        _syscallVoid(\"System.Storage.Put\", data);\n    }\n    \n    /**\n     * @dev Storage delete\n     */\n    function storageDelete(StorageContext memory context, bytes memory key) internal {\n        bytes memory data = abi.encode(context, key);\n        _syscallVoid(\"System.Storage.Delete\", data);\n    }\n    \n    /**\n     * @dev Storage find\n     */\n    function storageFind(StorageContext memory context, bytes memory prefix) \n        internal \n        view \n        returns (Iterator memory) \n    {\n        // Neo N3 signature: Storage.Find(context, prefix, options)\n        bytes memory data = abi.encode(context, prefix, uint8(0));\n        bytes memory result = _syscallBytes(\"System.Storage.Find\", data);\n        return abi.decode(result, (Iterator));\n    }\n\n    /**\n     * @dev Storage find with options\n     */\n    function storageFind(\n        StorageContext memory context,\n        bytes memory prefix,\n        uint8 options\n    ) internal view returns (Iterator memory) {\n        bytes memory data = abi.encode(context, prefix, options);\n        bytes memory result = _syscallBytes(\"System.Storage.Find\", data);\n        return abi.decode(result, (Iterator));\n    }\n\n    /**\n     * @dev Storage get (local context)\n     */\n    function storageGetLocal(bytes memory key)\n        internal\n        view\n        returns (bytes memory)\n    {\n        bytes memory data = abi.encode(key);\n        return _syscallBytes(\"System.Storage.Local.Get\", data);\n    }\n\n    /**\n     * @dev Storage put (local context)\n     */\n    function storagePutLocal(bytes memory key, bytes memory value) internal {\n        bytes memory data = abi.encode(key, value);\n        _syscallVoid(\"System.Storage.Local.Put\", data);\n    }\n\n    /**\n     * @dev Storage delete (local context)\n     */\n    function storageDeleteLocal(bytes memory key) internal {\n        bytes memory data = abi.encode(key);\n        _syscallVoid(\"System.Storage.Local.Delete\", data);\n    }\n\n    /**\n     * @dev Storage find (local context)\n     */\n    function storageFindLocal(bytes memory prefix)\n        internal\n        view\n        returns (Iterator memory)\n    {\n        bytes memory data = abi.encode(prefix, uint8(0));\n        bytes memory result = _syscallBytes(\"System.Storage.Local.Find\", data);\n        return abi.decode(result, (Iterator));\n    }\n\n    /**\n     * @dev Storage find (local context) with options\n     */\n    function storageFindLocal(bytes memory prefix, uint8 options)\n        internal\n        view\n        returns (Iterator memory)\n    {\n        bytes memory data = abi.encode(prefix, options);\n        bytes memory result = _syscallBytes(\"System.Storage.Local.Find\", data);\n        return abi.decode(result, (Iterator));\n    }\n    \n    // ========== Runtime System Calls ==========\n    \n    /**\n     * @dev Check witness\n     */\n    function checkWitness(address hash) internal view returns (bool) {\n        bytes memory data = abi.encode(hash);\n        return _syscall(\"System.Runtime.CheckWitness\", data) != 0;\n    }\n\n    /**\n     * @dev Check witness (public key)\n     */\n    function checkWitness(bytes memory publicKey) internal view returns (bool) {\n        bytes memory data = abi.encode(publicKey);\n        return _syscall(\"System.Runtime.CheckWitness\", data) != 0;\n    }\n    \n    /**\n     * @dev Get time (block timestamp)\n     */\n    function getTime() internal view returns (uint256) {\n        return _syscall(\"System.Runtime.GetTime\", \"\");\n    }\n    \n    /**\n     * @dev Get gas left\n     */\n    function gasLeft() internal view returns (uint256) {\n        return _syscall(\"System.Runtime.GasLeft\", \"\");\n    }\n    \n    /**\n     * @dev Get platform information\n     */\n    function getPlatform() internal view returns (string memory) {\n        bytes memory result = _syscallBytes(\"System.Runtime.Platform\", \"\");\n        return abi.decode(result, (string));\n    }\n    \n    /**\n     * @dev Get trigger type\n     */\n    function getTrigger() internal view returns (uint8) {\n        return uint8(_syscall(\"System.Runtime.GetTrigger\", \"\"));\n    }\n    \n    /**\n     * @dev Emit notification\n     */\n    function notify(bytes memory data) internal {\n        bytes memory params = abi.encode(data);\n        _syscallVoid(\"System.Runtime.Notify\", params);\n    }\n    \n    /**\n     * @dev Get notifications\n     */\n    function getNotifications(address hash) internal view returns (Notification[] memory) {\n        bytes memory data = abi.encode(hash);\n        bytes memory result = _syscallBytes(\"System.Runtime.GetNotifications\", data);\n        return abi.decode(result, (Notification[]));\n    }\n\n    /**\n     * @dev Get all notifications\n     */\n    function getNotifications() internal view returns (Notification[] memory) {\n        bytes memory result = _syscallBytes(\"System.Runtime.GetNotifications\", \"\");\n        return abi.decode(result, (Notification[]));\n    }\n    \n    /**\n     * @dev Log message\n     */\n    function log(string memory message) internal {\n        bytes memory data = abi.encode(message);\n        _syscallVoid(\"System.Runtime.Log\", data);\n    }\n\n    /**\n     * @dev Get current transaction signers\n     */\n    function getCurrentSigners() internal view returns (Signer[] memory) {\n        bytes memory result = _syscallBytes(\"System.Runtime.CurrentSigners\", \"\");\n        return abi.decode(result, (Signer[]));\n    }\n    \n    // ========== Cryptographic System Calls ==========\n\n    /**\n     * @dev Check signature against current script container\n     */\n    function checkSig(bytes memory publicKey, bytes memory signature) internal view returns (bool) {\n        bytes memory data = abi.encode(publicKey, signature);\n        return _syscall(\"System.Crypto.CheckSig\", data) != 0;\n    }\n\n    /**\n     * @dev Check multi-signature against current script container\n     */\n    function checkMultisig(bytes[] memory publicKeys, bytes[] memory signatures) internal view returns (bool) {\n        bytes memory data = abi.encode(publicKeys, signatures);\n        return _syscall(\"System.Crypto.CheckMultisig\", data) != 0;\n    }\n    \n    /**\n     * @dev SHA256 hash\n     */\n    function sha256(bytes memory data) internal view returns (bytes32) {\n        bytes memory params = abi.encode(data);\n        bytes memory result = contractCall(CRYPTO_LIB, \"sha256\", params);\n        return abi.decode(result, (bytes32));\n    }\n    \n    /**\n     * @dev RIPEMD160 hash\n     */\n    function ripemd160(bytes memory data) internal view returns (bytes20) {\n        bytes memory params = abi.encode(data);\n        bytes memory result = contractCall(CRYPTO_LIB, \"ripemd160\", params);\n        return abi.decode(result, (bytes20));\n    }\n\n    /**\n     * @dev Keccak-256 hash (CryptoLib native call, added at Neo N3 Cockatrice hardfork)\n     *\n     * NOTE: Solidity's built-in `keccak256()` is also lowered to this native call\n     * by the neo-devpack-solidity compiler. This explicit wrapper is provided for\n     * discoverability when calling through the Syscalls namespace.\n     */\n    function neoKeccak256(bytes memory data) internal view returns (bytes32) {\n        bytes memory params = abi.encode(data);\n        bytes memory result = contractCall(CRYPTO_LIB, \"keccak256\", params);\n        return abi.decode(result, (bytes32));\n    }\n\n    // NamedCurveHash values (Neo.SmartContract.Native.NamedCurveHash)\n    uint8 constant SECP256K1_SHA256 = 22;\n    uint8 constant SECP256R1_SHA256 = 23;\n    uint8 constant SECP256K1_KECCAK256 = 122;\n    uint8 constant SECP256R1_KECCAK256 = 123;\n    \n    /**\n     * @dev Verify ECDSA signature\n     */\n    function verifyWithECDsa(\n        bytes32 hash,\n        bytes memory publicKey,\n        bytes memory signature,\n        uint8 curve\n    ) internal view returns (bool) {\n        bytes memory data = abi.encode(hash, publicKey, signature, curve);\n        bytes memory result = contractCall(CRYPTO_LIB, \"verifyWithECDsa\", data);\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Verify ECDSA signature (message bytes)\n     */\n    function verifyWithECDsa(\n        bytes memory message,\n        bytes memory publicKey,\n        bytes memory signature,\n        uint8 curve\n    ) internal view returns (bool) {\n        bytes memory data = abi.encode(message, publicKey, signature, curve);\n        bytes memory result = contractCall(CRYPTO_LIB, \"verifyWithECDsa\", data);\n        return abi.decode(result, (bool));\n    }\n    \n    /**\n     * @dev Murmur32 hash\n     */\n    function murmur32(bytes memory data, uint32 seed) internal view returns (bytes4) {\n        bytes memory params = abi.encode(data, seed);\n        bytes memory result = contractCall(CRYPTO_LIB, \"murmur32\", params);\n        return abi.decode(result, (bytes4));\n    }\n\n    /**\n     * @dev Recover secp256k1 public key from signature\n     */\n    function recoverSecp256K1(bytes memory messageHash, bytes memory signature) internal view returns (bytes memory) {\n        bytes memory data = abi.encode(messageHash, signature);\n        return contractCall(CRYPTO_LIB, \"recoverSecp256K1\", data);\n    }\n\n    /**\n     * @dev Verify Ed25519 signature\n     */\n    function verifyWithEd25519(bytes memory message, bytes memory publicKey, bytes memory signature) internal view returns (bool) {\n        bytes memory data = abi.encode(message, publicKey, signature);\n        bytes memory result = contractCall(CRYPTO_LIB, \"verifyWithEd25519\", data);\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Serialize BLS12-381 point (opaque handle)\n     */\n    function bls12381Serialize(bytes memory point) internal view returns (bytes memory) {\n        bytes memory data = abi.encode(point);\n        return contractCall(CRYPTO_LIB, \"bls12381Serialize\", data);\n    }\n\n    /**\n     * @dev Deserialize BLS12-381 point (returns opaque handle)\n     */\n    function bls12381Deserialize(bytes memory data) internal view returns (bytes memory) {\n        bytes memory params = abi.encode(data);\n        return contractCall(CRYPTO_LIB, \"bls12381Deserialize\", params);\n    }\n\n    /**\n     * @dev Compare BLS12-381 points\n     */\n    function bls12381Equal(bytes memory x, bytes memory y) internal view returns (bool) {\n        bytes memory data = abi.encode(x, y);\n        bytes memory result = contractCall(CRYPTO_LIB, \"bls12381Equal\", data);\n        return abi.decode(result, (bool));\n    }\n\n    /**\n     * @dev Add BLS12-381 points\n     */\n    function bls12381Add(bytes memory x, bytes memory y) internal view returns (bytes memory) {\n        bytes memory data = abi.encode(x, y);\n        return contractCall(CRYPTO_LIB, \"bls12381Add\", data);\n    }\n\n    /**\n     * @dev Multiply BLS12-381 point by scalar\n     */\n    function bls12381Mul(bytes memory x, bytes memory mul, bool neg) internal view returns (bytes memory) {\n        bytes memory data = abi.encode(x, mul, neg);\n        return contractCall(CRYPTO_LIB, \"bls12381Mul\", data);\n    }\n\n    /**\n     * @dev Pairing operation for BLS12-381\n     */\n    function bls12381Pairing(bytes memory g1, bytes memory g2) internal view returns (bytes memory) {\n        bytes memory data = abi.encode(g1, g2);\n        return contractCall(CRYPTO_LIB, \"bls12381Pairing\", data);\n    }\n    \n    // ========== StdLib System Calls ==========\n\n    /**\n     * @dev Serialize stack item\n     */\n    function serialize(bytes memory data) internal view returns (bytes memory) {\n        bytes memory params = abi.encode(data);\n        return contractCall(STD_LIB, \"serialize\", params);\n    }\n\n    /**\n     * @dev Deserialize stack item\n     */\n    function deserialize(bytes memory data) internal view returns (bytes memory) {\n        bytes memory params = abi.encode(data);\n        return contractCall(STD_LIB, \"deserialize\", params);\n    }\n\n    /**\n     * @dev Integer to string (base 10)\n     */\n    function itoa(int256 value) internal view returns (string memory) {\n        bytes memory params = abi.encode(value);\n        bytes memory result = contractCall(STD_LIB, \"itoa\", params);\n        return abi.decode(result, (string));\n    }\n\n    /**\n     * @dev Integer to string with base (10 or 16)\n     */\n    function itoa(int256 value, uint8 base) internal view returns (string memory) {\n        bytes memory params = abi.encode(value, base);\n        bytes memory result = contractCall(STD_LIB, \"itoa\", params);\n        return abi.decode(result, (string));\n    }\n\n    /**\n     * @dev String to integer (base 10)\n     */\n    function atoi(string memory value) internal view returns (int256) {\n        bytes memory params = abi.encode(value);\n        bytes memory result = contractCall(STD_LIB, \"atoi\", params);\n        return abi.decode(result, (int256));\n    }\n\n    /**\n     * @dev String to integer with base (10 or 16)\n     */\n    function atoi(string memory value, uint8 base) internal view returns (int256) {\n        bytes memory params = abi.encode(value, base);\n        bytes memory result = contractCall(STD_LIB, \"atoi\", params);\n        return abi.decode(result, (int256));\n    }\n\n    // ========== JSON System Calls ==========\n    \n    /**\n     * @dev Serialize to JSON\n     */\n    function jsonSerialize(bytes memory data) internal view returns (bytes memory) {\n        bytes memory params = abi.encode(data);\n        return contractCall(STD_LIB, \"jsonSerialize\", params);\n    }\n    \n    /**\n     * @dev Deserialize from JSON\n     */\n    function jsonDeserialize(bytes memory json) internal view returns (bytes memory) {\n        bytes memory params = abi.encode(json);\n        return contractCall(STD_LIB, \"jsonDeserialize\", params);\n    }\n    \n    // ========== Base64 System Calls ==========\n    \n    /**\n     * @dev Base64 encode\n     */\n    function base64Encode(bytes memory data) internal view returns (string memory) {\n        bytes memory params = abi.encode(data);\n        bytes memory result = contractCall(STD_LIB, \"base64Encode\", params);\n        return abi.decode(result, (string));\n    }\n    \n    /**\n     * @dev Base64 decode\n     */\n    function base64Decode(string memory data) internal view returns (bytes memory) {\n        bytes memory params = abi.encode(data);\n        return contractCall(STD_LIB, \"base64Decode\", params);\n    }\n\n    /**\n     * @dev Base64Url encode\n     */\n    function base64UrlEncode(string memory data) internal view returns (string memory) {\n        bytes memory params = abi.encode(data);\n        bytes memory result = contractCall(STD_LIB, \"base64UrlEncode\", params);\n        return abi.decode(result, (string));\n    }\n\n    /**\n     * @dev Base64Url decode\n     */\n    function base64UrlDecode(string memory data) internal view returns (string memory) {\n        bytes memory params = abi.encode(data);\n        bytes memory result = contractCall(STD_LIB, \"base64UrlDecode\", params);\n        return abi.decode(result, (string));\n    }\n\n    // ========== Base58 System Calls ==========\n\n    /**\n     * @dev Base58 encode\n     */\n    function base58Encode(bytes memory data) internal view returns (string memory) {\n        bytes memory params = abi.encode(data);\n        bytes memory result = contractCall(STD_LIB, \"base58Encode\", params);\n        return abi.decode(result, (string));\n    }\n\n    /**\n     * @dev Base58 decode\n     */\n    function base58Decode(string memory data) internal view returns (bytes memory) {\n        bytes memory params = abi.encode(data);\n        return contractCall(STD_LIB, \"base58Decode\", params);\n    }\n\n    /**\n     * @dev Base58Check encode\n     */\n    function base58CheckEncode(bytes memory data) internal view returns (string memory) {\n        bytes memory params = abi.encode(data);\n        bytes memory result = contractCall(STD_LIB, \"base58CheckEncode\", params);\n        return abi.decode(result, (string));\n    }\n\n    /**\n     * @dev Base58Check decode\n     */\n    function base58CheckDecode(string memory data) internal view returns (bytes memory) {\n        bytes memory params = abi.encode(data);\n        return contractCall(STD_LIB, \"base58CheckDecode\", params);\n    }\n\n    // ========== Hex Utilities ==========\n\n    /**\n     * @dev Hex encode\n     */\n    function hexEncode(bytes memory data) internal view returns (string memory) {\n        bytes memory params = abi.encode(data);\n        bytes memory result = contractCall(STD_LIB, \"hexEncode\", params);\n        return abi.decode(result, (string));\n    }\n\n    /**\n     * @dev Hex decode\n     */\n    function hexDecode(string memory data) internal view returns (bytes memory) {\n        bytes memory params = abi.encode(data);\n        return contractCall(STD_LIB, \"hexDecode\", params);\n    }\n\n    // ========== Memory and String Utilities ==========\n\n    /**\n     * @dev Compare two byte arrays\n     */\n    function memoryCompare(bytes memory left, bytes memory right) internal view returns (int256) {\n        bytes memory params = abi.encode(left, right);\n        bytes memory result = contractCall(STD_LIB, \"memoryCompare\", params);\n        return abi.decode(result, (int256));\n    }\n\n    /**\n     * @dev Search for a value in memory (start at 0)\n     */\n    function memorySearch(bytes memory mem, bytes memory value) internal view returns (int256) {\n        bytes memory params = abi.encode(mem, value);\n        bytes memory result = contractCall(STD_LIB, \"memorySearch\", params);\n        return abi.decode(result, (int256));\n    }\n\n    /**\n     * @dev Search for a value in memory (start at offset)\n     */\n    function memorySearch(bytes memory mem, bytes memory value, int256 start) internal view returns (int256) {\n        bytes memory params = abi.encode(mem, value, start);\n        bytes memory result = contractCall(STD_LIB, \"memorySearch\", params);\n        return abi.decode(result, (int256));\n    }\n\n    /**\n     * @dev Search for a value in memory (start at offset, optionally backward)\n     */\n    function memorySearch(bytes memory mem, bytes memory value, int256 start, bool backward)\n        internal\n        view\n        returns (int256)\n    {\n        bytes memory params = abi.encode(mem, value, start, backward);\n        bytes memory result = contractCall(STD_LIB, \"memorySearch\", params);\n        return abi.decode(result, (int256));\n    }\n\n    /**\n     * @dev Split a string by separator\n     */\n    function stringSplit(string memory value, string memory separator) internal view returns (string[] memory) {\n        bytes memory params = abi.encode(value, separator);\n        bytes memory result = contractCall(STD_LIB, \"stringSplit\", params);\n        return abi.decode(result, (string[]));\n    }\n\n    /**\n     * @dev Split a string by separator with optional empty removal\n     */\n    function stringSplit(\n        string memory value,\n        string memory separator,\n        bool removeEmptyEntries\n    ) internal view returns (string[] memory) {\n        bytes memory params = abi.encode(value, separator, removeEmptyEntries);\n        bytes memory result = contractCall(STD_LIB, \"stringSplit\", params);\n        return abi.decode(result, (string[]));\n    }\n\n    /**\n     * @dev Get string length in text elements\n     */\n    function strLen(string memory value) internal view returns (uint256) {\n        bytes memory params = abi.encode(value);\n        bytes memory result = contractCall(STD_LIB, \"strLen\", params);\n        return abi.decode(result, (uint256));\n    }\n    \n    // ========== Iterator System Calls ==========\n    \n    /**\n     * @dev Get next iterator value\n     */\n    function iteratorNext(Iterator memory iterator) internal returns (bool) {\n        bytes memory data = abi.encode(iterator);\n        return _syscall(\"System.Iterator.Next\", data) != 0;\n    }\n    \n    /**\n     * @dev Get iterator value\n     */\n    function iteratorValue(Iterator memory iterator) internal view returns (bytes memory) {\n        bytes memory data = abi.encode(iterator);\n        return _syscallBytes(\"System.Iterator.Value\", data);\n    }\n    \n    // ========== Internal Syscall Implementation ==========\n    \n    /**\n     * @dev Internal syscall that returns uint256\n     */\n    function _syscall(string memory method, bytes memory params) private view returns (uint256) {\n        // Production syscall implementation using Neo VM native interface\n        bytes memory callData = abi.encodeWithSignature(\"neoSyscall(string,bytes)\", method, params);\n        \n        (bool success, bytes memory result) = address(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).staticcall(callData);\n        \n        if (!success || result.length < 32) {\n            // Fallback to method-specific implementations\n            return _handleSyscallFallback(method, params);\n        }\n        \n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Fallback syscall implementations for specific methods\n     */\n    function _handleSyscallFallback(string memory method, bytes memory params) private view returns (uint256) {\n        bytes32 methodHash = keccak256(bytes(method));\n        \n        if (methodHash == keccak256(\"System.Blockchain.GetHeight\")) {\n            return block.number;\n        } else if (methodHash == keccak256(\"System.Runtime.GetTime\")) {\n            return block.timestamp;\n        } else if (methodHash == keccak256(\"System.Runtime.GasLeft\")) {\n            // Fallback runtime does not expose gas accounting.\n            return 0;\n        } else if (methodHash == keccak256(\"System.Runtime.CheckWitness\")) {\n            address account = abi.decode(params, (address));\n            return account == msg.sender ? 1 : 0;\n        }\n        \n        return 0;\n    }\n    \n    /**\n     * @dev Internal syscall that returns bytes\n     */\n    function _syscallBytes(string memory method, bytes memory params) private view returns (bytes memory) {\n        // Production syscall implementation for bytes return values\n        bytes memory callData = abi.encodeWithSignature(\"neoSyscallBytes(string,bytes)\", method, params);\n        \n        (bool success, bytes memory result) = address(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).staticcall(callData);\n        \n        if (!success) {\n            // Fallback to method-specific implementations\n            return _handleBytesSyscallFallback(method, params);\n        }\n        \n        return result;\n    }\n    \n    /**\n     * @dev Fallback syscall implementations for bytes methods\n     */\n    function _handleBytesSyscallFallback(string memory method, bytes memory params) private view returns (bytes memory) {\n        bytes32 methodHash = keccak256(bytes(method));\n        \n        if (methodHash == keccak256(\"System.Runtime.GetExecutingScriptHash\")) {\n            return abi.encode(address(this));\n        } else if (methodHash == keccak256(\"System.Runtime.GetCallingScriptHash\")) {\n            return abi.encode(msg.sender);\n        }\n        \n        return \"\";\n    }\n\n    /**\n     * @dev Internal syscall that returns void\n     */\n    function _syscallVoid(string memory method, bytes memory params) private {\n        // Production syscall implementation for void return methods\n        bytes memory callData = abi.encodeWithSignature(\"neoSyscallVoid(string,bytes)\", method, params);\n        \n        (bool success, ) = address(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).call(callData);\n        \n        if (!success) {\n            // Fallback to method-specific implementations\n            _handleVoidSyscallFallback(method, params);\n        }\n    }\n    \n    /**\n     * @dev Fallback syscall implementations for void methods\n     */\n    function _handleVoidSyscallFallback(string memory method, bytes memory params) private {\n        bytes32 methodHash = keccak256(bytes(method));\n        \n        if (methodHash == keccak256(\"System.Storage.Put\")) {\n            return;\n        } else if (methodHash == keccak256(\"System.Storage.Delete\")) {\n            return;\n        } else if (methodHash == keccak256(\"System.Runtime.Notify\")) {\n            return;\n        }\n    }\n    \n    // ========== Data Structures ==========\n    \n    // Ledger.getBlock returns a TrimmedBlock stack item, not the full block payload.\n    struct Block {\n        bytes32 hash;\n        uint256 version;\n        bytes32 previousHash;\n        bytes32 merkleRoot;\n        uint256 timestamp;\n        uint256 nonce;\n        uint256 index;\n        uint256 primaryIndex;\n        address nextConsensus;\n        uint256 txCount;\n    }\n    \n    // Ledger.getTransaction returns the base transaction fields (no signers/witnesses).\n    struct Transaction {\n        bytes32 hash;\n        uint256 version;\n        uint256 nonce;\n        address sender;\n        uint256 systemFee;\n        uint256 networkFee;\n        uint256 validUntilBlock;\n        bytes script;\n    }\n    \n    struct Witness {\n        bytes invocationScript;\n        bytes verificationScript;\n    }\n\n    uint8 constant WITNESS_RULE_DENY = 0x00;\n    uint8 constant WITNESS_RULE_ALLOW = 0x01;\n\n    uint8 constant WITNESS_CONDITION_BOOLEAN = 0x00;\n    uint8 constant WITNESS_CONDITION_NOT = 0x01;\n    uint8 constant WITNESS_CONDITION_AND = 0x02;\n    uint8 constant WITNESS_CONDITION_OR = 0x03;\n    uint8 constant WITNESS_CONDITION_SCRIPT_HASH = 0x18;\n    uint8 constant WITNESS_CONDITION_GROUP = 0x19;\n    uint8 constant WITNESS_CONDITION_CALLED_BY_ENTRY = 0x20;\n    uint8 constant WITNESS_CONDITION_CALLED_BY_CONTRACT = 0x28;\n    uint8 constant WITNESS_CONDITION_CALLED_BY_GROUP = 0x29;\n\n    // WitnessCondition is represented as a NeoVM Array:\n    // [type, ...condition-specific data]. Use StdLib.serialize/deserialize\n    // if you need to inspect it in Solidity.\n    struct WitnessRule {\n        uint8 action;\n        bytes condition;\n    }\n    \n    // WitnessScope bit flags (see Neo WitnessScope enum).\n    uint8 constant WITNESS_SCOPE_NONE = 0x00;\n    uint8 constant WITNESS_SCOPE_CALLED_BY_ENTRY = 0x01;\n    uint8 constant WITNESS_SCOPE_CUSTOM_CONTRACTS = 0x10;\n    uint8 constant WITNESS_SCOPE_CUSTOM_GROUPS = 0x20;\n    uint8 constant WITNESS_SCOPE_WITNESS_RULES = 0x40;\n    uint8 constant WITNESS_SCOPE_GLOBAL = 0x80;\n\n    struct Signer {\n        address account;\n        uint8 scopes;\n        address[] allowedContracts;\n        bytes[] allowedGroups;\n        // Witness rules (only present when scopes includes WITNESS_SCOPE_WITNESS_RULES).\n        WitnessRule[] rules;\n    }\n    \n    struct StorageContext {\n        int256 id;\n        bool isReadOnly;\n    }\n    \n    struct Iterator {\n        uint256 id;\n        bool hasNext;\n        bytes currentKey;\n        bytes currentValue;\n    }\n    \n    struct Notification {\n        address scriptHash;\n        string eventName;\n        // State array passed to Runtime.notify(...)\n        bytes[] state;\n    }\n\n    // ContractManagement.getContract returns:\n    // [id, updateCounter, hash, nef, manifestStruct]\n    struct ContractStateNative {\n        int256 id;\n        uint256 updateCounter;\n        address hash;\n        bytes nef;\n        bytes manifest;\n    }\n    \n    // TriggerType values (Neo.SmartContract.TriggerType)\n    uint8 constant TRIGGER_ON_PERSIST = 0x01;\n    uint8 constant TRIGGER_POST_PERSIST = 0x02;\n    uint8 constant TRIGGER_VERIFICATION = 0x20;\n    uint8 constant TRIGGER_APPLICATION = 0x40;\n    uint8 constant TRIGGER_SYSTEM = TRIGGER_ON_PERSIST | TRIGGER_POST_PERSIST;\n    uint8 constant TRIGGER_ALL = TRIGGER_SYSTEM | TRIGGER_VERIFICATION | TRIGGER_APPLICATION;\n    \n    // ========== Advanced Syscalls ==========\n    \n    /**\n     * @dev Get current random number\n     */\n    function getCurrentRandom() internal view returns (uint256) {\n        return _syscall(\"System.Runtime.GetRandom\", \"\");\n    }\n    \n    /**\n     * @dev Get network magic number\n     */\n    function getNetwork() internal view returns (uint32) {\n        return uint32(_syscall(\"System.Runtime.GetNetwork\", \"\"));\n    }\n    \n    /**\n     * @dev Get address version\n     */\n    function getAddressVersion() internal view returns (uint8) {\n        return uint8(_syscall(\"System.Runtime.GetAddressVersion\", \"\"));\n    }\n    \n    /**\n     * @dev Burn GAS\n     */\n    function burnGas(uint256 amount) internal {\n        bytes memory data = abi.encode(amount);\n        _syscallVoid(\"System.Runtime.BurnGas\", data);\n    }\n    \n    /**\n     * @dev Get invocation counter\n     */\n    function getInvocationCounter() internal view returns (uint256) {\n        return _syscall(\"System.Runtime.GetInvocationCounter\", \"\");\n    }\n    \n    // ========== Policy System Calls ==========\n    \n    /**\n     * @dev Get fee per byte\n     */\n    function getFeePerByte() internal view returns (uint256) {\n        bytes memory result = contractCall(POLICY_CONTRACT, \"getFeePerByte\", \"\");\n        return abi.decode(result, (uint256));\n    }\n    \n    /**\n     * @dev Get exec fee factor\n     */\n    function getExecFeeFactor() internal view returns (uint32) {\n        bytes memory result = contractCall(POLICY_CONTRACT, \"getExecFeeFactor\", \"\");\n        return abi.decode(result, (uint32));\n    }\n\n    /**\n     * @dev Get exec fee factor in picoGAS units\n     */\n    function getExecPicoFeeFactor() internal view returns (uint256) {\n        bytes memory result = contractCall(POLICY_CONTRACT, \"getExecPicoFeeFactor\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get storage price\n     */\n    function getStoragePrice() internal view returns (uint256) {\n        bytes memory result = contractCall(POLICY_CONTRACT, \"getStoragePrice\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get block milliseconds\n     */\n    function getMillisecondsPerBlock() internal view returns (uint256) {\n        bytes memory result = contractCall(POLICY_CONTRACT, \"getMillisecondsPerBlock\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get max valid-until-block increment\n     */\n    function getMaxValidUntilBlockIncrement() internal view returns (uint256) {\n        bytes memory result = contractCall(POLICY_CONTRACT, \"getMaxValidUntilBlockIncrement\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get max traceable blocks\n     */\n    function getMaxTraceableBlocks() internal view returns (uint256) {\n        bytes memory result = contractCall(POLICY_CONTRACT, \"getMaxTraceableBlocks\", \"\");\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Get attribute fee\n     */\n    function getAttributeFee(uint8 attributeType) internal view returns (uint256) {\n        bytes memory data = abi.encode(attributeType);\n        bytes memory result = contractCall(POLICY_CONTRACT, \"getAttributeFee\", data);\n        return abi.decode(result, (uint256));\n    }\n\n    /**\n     * @dev Check if account is blocked\n     */\n    function isBlocked(address account) internal view returns (bool) {\n        bytes memory data = abi.encode(account);\n        bytes memory result = contractCall(POLICY_CONTRACT, \"isBlocked\", data);\n        return abi.decode(result, (bool));\n    }\n    \n    // ========== Oracle System Calls ==========\n    \n    /**\n     * @dev Make oracle request\n     */\n    function oracleRequest(\n        string memory url,\n        string memory filter,\n        string memory callback,\n        bytes memory userData,\n        uint256 gasForResponse\n    ) internal {\n        bytes memory data = abi.encode(url, filter, callback, userData, gasForResponse);\n        contractCall(ORACLE_CONTRACT, \"request\", data);\n    }\n    \n    /**\n     * @dev Get oracle price\n     */\n    function getOraclePrice() internal view returns (uint256) {\n        bytes memory result = contractCall(ORACLE_CONTRACT, \"getPrice\", \"\");\n        return abi.decode(result, (uint256));\n    }\n    \n    // ========== Role Management System Calls ==========\n    \n    /**\n     * @dev Get designated by role\n     */\n    function getDesignatedByRole(bytes1 role, uint256 index) internal view returns (bytes[] memory) {\n        bytes memory data = abi.encode(role, index);\n        bytes memory result = contractCall(ROLE_MANAGEMENT, \"getDesignatedByRole\", data);\n        return abi.decode(result, (bytes[]));\n    }\n    \n    // ========== Utility Functions ==========\n    \n    /**\n     * @dev Convert script hash to address\n     */\n    function scriptHashToAddress(bytes20 scriptHash) internal pure returns (address) {\n        return address(uint160(uint256(bytes32(scriptHash))));\n    }\n    \n    /**\n     * @dev Convert address to script hash\n     */\n    function addressToScriptHash(address addr) internal pure returns (bytes20) {\n        return bytes20(uint160(addr));\n    }\n    \n    /**\n     * @dev Validate Neo address format\n     */\n    function isValidAddress(address addr) internal pure returns (bool) {\n        return addr != address(0) && uint160(addr) != 0;\n    }\n    \n    /**\n     * @dev Get contract NEF (script container)\n     *\n     * NOTE: The neo-devpack-solidity compiler treats this as an intrinsic and lowers it\n     * to `ContractManagement.getContract(contractHash).nef`.\n     */\n    function getContractScript(address contractHash) internal view returns (bytes memory) {\n        bytes memory data = abi.encode(contractHash);\n        bytes memory result = contractCall(CONTRACT_MANAGEMENT, \"getContract\", data);\n        if (result.length == 0) {\n            return \"\";\n        }\n        ContractStateNative memory state = abi.decode(result, (ContractStateNative));\n        return state.nef;\n    }\n    \n    /**\n     * @dev Check if contract exists\n     *\n     * NOTE: The compiler lowers this helper to `ContractManagement.isContract(contractHash)`\n     * on Neo N3 for correctness and efficiency.\n     */\n    function contractExists(address contractHash) internal view returns (bool) {\n        bytes memory data = abi.encode(contractHash);\n        bytes memory result = contractCall(CONTRACT_MANAGEMENT, \"isContract\", data);\n        return abi.decode(result, (bool));\n    }\n}\n"
    },
    "libraries/Neo.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title Neo N3 Blockchain Utilities\n * @dev Comprehensive library for Neo N3 blockchain integration\n * @author Jimmy <jimmy@r3e.network>\n * \n * This library provides high-level access to Neo N3 blockchain features:\n * - Block and transaction information\n * - Account and balance management\n * - Cryptographic operations\n * - Network state queries\n * - Gas and fee calculations\n */\n\nimport \"../contracts/Syscalls.sol\";\nimport \"../contracts/NativeCalls.sol\";\n\nlibrary Neo {\n    using Syscalls for *;\n    using NativeCalls for *;\n    \n    // ========== Block Information ==========\n    \n    /**\n     * @dev Get current block information\n     */\n    function getCurrentBlock() internal view returns (\n        uint256 index,\n        bytes32 hash,\n        uint256 timestamp,\n        bytes32 merkleRoot\n    ) {\n        Syscalls.Block memory currentBlock = Syscalls.getBlock(Syscalls.getCurrentIndex());\n        return (currentBlock.index, currentBlock.hash, currentBlock.timestamp, currentBlock.merkleRoot);\n    }\n    \n    /**\n     * @dev Get block by index\n     */\n    function getBlockByIndex(uint256 index) internal view returns (Syscalls.Block memory) {\n        return Syscalls.getBlock(index);\n    }\n    \n    /**\n     * @dev Get current block height\n     */\n    function getBlockHeight() internal view returns (uint256) {\n        return Syscalls.getCurrentIndex();\n    }\n    \n    /**\n     * @dev Get block timestamp\n     */\n    function getBlockTime() internal view returns (uint256) {\n        return Syscalls.getTime();\n    }\n    \n    // ========== Transaction Information ==========\n    \n    /**\n     * @dev Get transaction information\n     */\n    function getTransaction(bytes32 txHash) internal view returns (\n        bytes32 hash,\n        uint256 nonce,\n        address sender,\n        uint256 gasLimit,\n        uint256 gasPrice\n    ) {\n        Syscalls.Transaction memory tx = Syscalls.getTransaction(txHash);\n        return (tx.hash, tx.nonce, tx.sender, tx.systemFee + tx.networkFee, tx.networkFee);\n    }\n    \n    /**\n     * @dev Get transaction height\n     */\n    function getTransactionHeight(bytes32 txHash) internal view returns (int256) {\n        return Syscalls.getTransactionHeight(txHash);\n    }\n    \n    /**\n     * @dev Check if transaction exists\n     */\n    function transactionExists(bytes32 txHash) internal view returns (bool) {\n        return getTransactionHeight(txHash) >= 0;\n    }\n    \n    // ========== Account and Balance Management ==========\n    \n    /**\n     * @dev Get NEO balance of account\n     */\n    function getNeoBalance(address account) internal view returns (uint256) {\n        return NativeCalls.neoBalanceOf(account);\n    }\n    \n    /**\n     * @dev Get GAS balance of account\n     */\n    function getGasBalance(address account) internal view returns (uint256) {\n        return NativeCalls.gasBalanceOf(account);\n    }\n    \n    /**\n     * @dev Transfer NEO tokens\n     */\n    function transferNeo(address from, address to, uint256 amount) internal returns (bool) {\n        return NativeCalls.neoTransfer(from, to, amount, \"\");\n    }\n    \n    /**\n     * @dev Transfer GAS tokens\n     */\n    function transferGas(address from, address to, uint256 amount) internal returns (bool) {\n        return NativeCalls.gasTransfer(from, to, amount, \"\");\n    }\n    \n    /**\n     * @dev Get account's total portfolio value (NEO + GAS)\n     */\n    function getPortfolioValue(address account) internal view returns (\n        uint256 neoBalance,\n        uint256 gasBalance,\n        uint256 totalValueInGas\n    ) {\n        neoBalance = getNeoBalance(account);\n        gasBalance = getGasBalance(account);\n        \n        // Simple approximation: 1 NEO = current gas per block * blocks per day\n        uint256 gasPerBlock = NativeCalls.getGasPerBlock();\n        uint256 blocksPerDay = 5760; // Approximately 15 second blocks\n        uint256 neoValueInGas = neoBalance * gasPerBlock * blocksPerDay;\n        \n        totalValueInGas = gasBalance + neoValueInGas;\n    }\n    \n    // ========== Cryptographic Operations ==========\n    \n    /**\n     * @dev Verify signature with witness\n     */\n    function verifyWithWitness(address account) internal view returns (bool) {\n        return Syscalls.checkWitness(account);\n    }\n    \n    /**\n     * @dev Verify ECDSA signature using the specified curve.\n     * @param curve Neo named curve ID (e.g. 23 = secp256r1, 22 = secp256k1)\n     */\n    function verifySignatureWithCurve(\n        bytes32 hash,\n        bytes memory publicKey,\n        bytes memory signature,\n        uint8 curve\n    ) internal view returns (bool) {\n        return Syscalls.verifyWithECDsa(hash, publicKey, signature, curve);\n    }\n\n    /**\n     * @dev Verify ECDSA signature (secp256r1, Neo's default curve).\n     */\n    function verifySignature(\n        bytes32 hash,\n        bytes memory publicKey,\n        bytes memory signature\n    ) internal view returns (bool) {\n        return Syscalls.verifyWithECDsa(hash, publicKey, signature, 23); // secp256r1\n    }\n\n    /**\n     * @dev SHA256 hash\n     */\n    function sha256Hash(bytes memory data) internal view returns (bytes32) {\n        return Syscalls.sha256(data);\n    }\n\n    /**\n     * @dev RIPEMD160 hash\n     */\n    function ripemd160Hash(bytes memory data) internal view returns (bytes20) {\n        return Syscalls.ripemd160(data);\n    }\n    \n    /**\n     * @dev Get random number\n     */\n    function getRandom() internal view returns (uint256) {\n        return Syscalls.getCurrentRandom();\n    }\n    \n    // ========== Contract Management ==========\n    \n    /**\n     * @dev Call another contract\n     */\n    function callContract(\n        address contractHash,\n        string memory method,\n        bytes memory params\n    ) internal returns (bytes memory) {\n        return Syscalls.contractCall(contractHash, method, params);\n    }\n    \n    /**\n     * @dev Deploy new contract\n     */\n    function deployContract(bytes memory nef, bytes memory manifest) internal returns (address) {\n        return NativeCalls.deployContract(nef, manifest);\n    }\n    \n    /**\n     * @dev Get contract information\n     */\n    function getContractInfo(address contractHash) internal view returns (\n        string memory name,\n        bytes memory script,\n        bytes memory manifest\n    ) {\n        NativeCalls.ContractState memory state = NativeCalls.getContract(contractHash);\n        return (\"Contract\", state.nef, state.manifest);\n    }\n    \n    /**\n     * @dev Check if contract exists\n     */\n    function contractExists(address contractHash) internal view returns (bool) {\n        return Syscalls.contractExists(contractHash);\n    }\n    \n    // ========== Network Information ==========\n    \n    /**\n     * @dev Get network magic number\n     */\n    function getNetworkMagic() internal view returns (uint32) {\n        return Syscalls.getNetwork();\n    }\n    \n    /**\n     * @dev Get current gas price\n     */\n    function getGasPrice() internal view returns (uint256) {\n        return NativeCalls.getFeePerByte();\n    }\n    \n    /**\n     * @dev Get storage price per byte\n     */\n    function getStoragePrice() internal view returns (uint256) {\n        return NativeCalls.getStoragePrice();\n    }\n    \n    /**\n     * @dev Estimate gas for operation\n     */\n    function estimateGas(bytes memory operation) internal view returns (uint256) {\n        // Base gas estimation based on operation size\n        uint256 baseGas = 1000000; // 0.01 GAS\n        uint256 dataGas = operation.length * 1000; // 0.00001 GAS per byte\n        \n        return baseGas + dataGas;\n    }\n    \n    // ========== Governance Functions ==========\n    \n    /**\n     * @dev Check if account is committee member\n     */\n    function isCommittee(address account) internal view returns (bool) {\n        return NativeCalls.isCommittee(account);\n    }\n    \n    /**\n     * @dev Get committee members\n     */\n    function getCommittee() internal view returns (bytes[] memory) {\n        return NativeCalls.getCommittee();\n    }\n    \n    /**\n     * @dev Get next block validators\n     */\n    function getValidators() internal view returns (address[] memory) {\n        return NativeCalls.getNextBlockValidators();\n    }\n    \n    /**\n     * @dev Check if account is validator\n     */\n    function isValidator(address account) internal view returns (bool) {\n        return NativeCalls.isValidator(account);\n    }\n    \n    /**\n     * @dev Vote for candidate\n     */\n    function vote(address account, bytes memory publicKey) internal returns (bool) {\n        return NativeCalls.vote(account, publicKey);\n    }\n    \n    // ========== Utility Functions ==========\n    \n    /**\n     * @dev Convert script hash to address\n     */\n    function scriptHashToAddress(bytes20 scriptHash) internal pure returns (address) {\n        return Syscalls.scriptHashToAddress(scriptHash);\n    }\n    \n    /**\n     * @dev Convert address to script hash\n     */\n    function addressToScriptHash(address addr) internal pure returns (bytes20) {\n        return Syscalls.addressToScriptHash(addr);\n    }\n    \n    /**\n     * @dev Validate Neo address\n     */\n    function isValidAddress(address addr) internal pure returns (bool) {\n        return Syscalls.isValidAddress(addr);\n    }\n    \n    /**\n     * @dev Get executing contract hash\n     */\n    function getExecutingContract() internal view returns (address) {\n        return Syscalls.getExecutingScriptHash();\n    }\n    \n    /**\n     * @dev Get calling contract hash\n     */\n    function getCallingContract() internal view returns (address) {\n        return Syscalls.getCallingScriptHash();\n    }\n    \n    /**\n     * @dev Get entry script hash\n     */\n    function getEntryScript() internal view returns (address) {\n        return Syscalls.getEntryScriptHash();\n    }\n    \n    // ========== Gas Management ==========\n    \n    /**\n     * @dev Get gas left in current execution\n     */\n    function gasLeft() internal view returns (uint256) {\n        return Syscalls.gasLeft();\n    }\n    \n    /**\n     * @dev Burn gas (for gas optimization)\n     */\n    function burnGas(uint256 amount) internal {\n        Syscalls.burnGas(amount);\n    }\n    \n    /**\n     * @dev Calculate storage cost\n     */\n    function calculateStorageCost(uint256 bytes_) internal view returns (uint256) {\n        return bytes_ * getStoragePrice();\n    }\n    \n    /**\n     * @dev Calculate deployment cost\n     */\n    function calculateDeploymentCost(uint256 nefSize, uint256 manifestSize) \n        internal \n        view \n        returns (uint256) \n    {\n        uint256 minimumFee = NativeCalls.getMinimumDeploymentFee();\n        uint256 storageCost = calculateStorageCost(nefSize + manifestSize);\n        return minimumFee + storageCost;\n    }\n    \n    // ========== Advanced Features ==========\n    \n    /**\n     * @dev Multi-signature verification\n     */\n    function verifyMultiSig(\n        bytes32 hash,\n        bytes[] memory publicKeys,\n        bytes[] memory signatures,\n        uint256 threshold\n    ) internal pure returns (bool) {\n        require(publicKeys.length >= threshold, \"Neo: insufficient public keys\");\n        require(signatures.length >= threshold, \"Neo: insufficient signatures\");\n        \n        uint256 validSignatures = 0;\n        \n        for (uint256 i = 0; i < signatures.length && validSignatures < threshold; i++) {\n            for (uint256 j = 0; j < publicKeys.length; j++) {\n                if (verifySignature(hash, publicKeys[j], signatures[i])) {\n                    validSignatures++;\n                    break;\n                }\n            }\n        }\n        \n        return validSignatures >= threshold;\n    }\n    \n    /**\n     * @dev Time-based operations\n     */\n    function isAfterBlock(uint256 blockHeight) internal view returns (bool) {\n        return getBlockHeight() > blockHeight;\n    }\n    \n    function isAfterTime(uint256 timestamp) internal view returns (bool) {\n        return getBlockTime() > timestamp;\n    }\n    \n    /**\n     * @dev Network health check\n     */\n    function getNetworkHealth() internal view returns (\n        uint256 blockHeight,\n        uint256 committeeSize,\n        uint256 validatorCount,\n        uint256 gasPerBlock,\n        bool isHealthy\n    ) {\n        blockHeight = getBlockHeight();\n        bytes[] memory committee = getCommittee();\n        address[] memory validators = getValidators();\n        committeeSize = committee.length;\n        validatorCount = validators.length;\n        gasPerBlock = NativeCalls.getGasPerBlock();\n        \n        // Simple health check\n        isHealthy = committeeSize >= 7 && validatorCount >= 4 && gasPerBlock > 0;\n    }\n    \n    /**\n     * @dev Oracle integration helper\n     */\n    function requestOracleData(\n        string memory url,\n        string memory filter,\n        string memory callback,\n        bytes memory userData\n    ) internal {\n        uint256 gasForResponse = 100000000; // 1 GAS\n        NativeCalls.requestOracleData(url, filter, callback, userData, gasForResponse);\n    }\n    \n    /**\n     * @dev Policy information\n     */\n    function getPolicyInfo() internal view returns (\n        uint256 feePerByte,\n        uint32 execFeeFactor,\n        uint256 storagePrice\n    ) {\n        feePerByte = NativeCalls.getFeePerByte();\n        execFeeFactor = NativeCalls.getExecFeeFactor();\n        storagePrice = NativeCalls.getStoragePrice();\n    }\n    \n    /**\n     * @dev Emergency functions\n     */\n    function emergencyBurnGas() internal {\n        uint256 gasRemaining = gasLeft();\n        if (gasRemaining > 1000000) { // Keep 0.01 GAS for cleanup\n            burnGas(gasRemaining - 1000000);\n        }\n    }\n    \n    /**\n     * @dev Platform information\n     */\n    function getPlatformInfo() internal view returns (\n        string memory platform,\n        uint32 network,\n        uint8 addressVersion\n    ) {\n        platform = Syscalls.getPlatform();\n        network = Syscalls.getNetwork();\n        addressVersion = Syscalls.getAddressVersion();\n    }\n    \n    /**\n     * @dev Safe contract call with error handling\n     */\n    function safeContractCall(\n        address contractHash,\n        string memory method,\n        bytes memory params\n    ) internal returns (bool success, bytes memory result) {\n        try Neo.callContract(contractHash, method, params) returns (bytes memory data) {\n            return (true, data);\n        } catch {\n            return (false, \"\");\n        }\n    }\n    \n    /**\n     * @dev Batch contract calls\n     */\n    function batchContractCalls(\n        address[] memory contracts,\n        string[] memory methods,\n        bytes[] memory params\n    ) internal returns (bytes[] memory results) {\n        require(contracts.length == methods.length, \"Neo: array length mismatch\");\n        require(contracts.length == params.length, \"Neo: array length mismatch\");\n        require(contracts.length > 0, \"Neo: empty arrays\");\n        require(contracts.length <= 10, \"Neo: too many calls\");\n        \n        results = new bytes[](contracts.length);\n        \n        for (uint256 i = 0; i < contracts.length; i++) {\n            (bool success, bytes memory result) = safeContractCall(contracts[i], methods[i], params[i]);\n            results[i] = success ? result : \"\";\n        }\n    }\n    \n    /**\n     * @dev Calculate optimal gas limit for operation\n     */\n    function calculateOptimalGasLimit(\n        uint256 baseOperations,\n        uint256 storageOperations,\n        uint256 contractCalls\n    ) internal view returns (uint256) {\n        uint256 baseGas = baseOperations * 100000; // 0.001 GAS per basic operation\n        uint256 storageGas = storageOperations * 1000000; // 0.01 GAS per storage operation\n        uint256 callGas = contractCalls * 10000000; // 0.1 GAS per contract call\n        \n        return baseGas + storageGas + callGas;\n    }\n}\n"
    },
    "libraries/Runtime.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title Neo N3 Runtime Library\n * @dev Runtime services and utilities for Neo N3 blockchain\n * @author Jimmy <jimmy@r3e.network>\n * \n * This library provides runtime services including:\n * - Event emission and notification system\n * - Witness verification and authorization\n * - Gas management and optimization\n * - Execution context information\n * - Error handling and debugging\n */\n\nimport \"../contracts/Syscalls.sol\";\nimport \"../contracts/NativeCalls.sol\";\n\nlibrary Runtime {\n    using Syscalls for *;\n    \n    // Events\n    event RuntimeInitialized();\n    event NotificationEmitted(string indexed eventName, bytes data);\n    event WitnessVerified(address indexed account, bool success);\n    event GasOptimization(uint256 saved, string technique);\n    \n    // ========== Event and Notification System ==========\n    \n    /**\n     * @dev Emit notification (maps to Runtime.Notify)\n     */\n    function notify(string memory eventName, bytes memory data) internal {\n        // Call Neo Runtime.Notify\n        bytes memory notificationData = abi.encode(eventName, data);\n        Syscalls.notify(notificationData);\n\n        emit NotificationEmitted(eventName, data);\n    }\n    \n    /**\n     * @dev Emit indexed notification with topics\n     */\n    function notifyIndexed(\n        string memory eventName,\n        bytes32[] memory topics,\n        bytes memory data\n    ) internal {\n        require(topics.length <= 4, \"Runtime: too many topics\");\n        \n        // Encode topics and data together\n        bytes memory indexedData = abi.encode(topics, data);\n        notify(eventName, indexedData);\n    }\n    \n    /**\n     * @dev Emit standard ERC-20 Transfer event\n     */\n    function notifyTransfer(address from, address to, uint256 amount) internal {\n        notify(\"Transfer\", abi.encode(from, to, amount));\n    }\n    \n    /**\n     * @dev Emit standard ERC-20 Approval event\n     */\n    function notifyApproval(address owner, address spender, uint256 amount) internal {\n        notify(\"Approval\", abi.encode(owner, spender, amount));\n    }\n    \n    /**\n     * @dev Emit NFT Transfer event\n     */\n    function notifyNFTTransfer(address from, address to, bytes32 tokenId) internal {\n        notify(\"Transfer\", abi.encode(from, to, 1, tokenId));\n    }\n    \n    /**\n     * @dev Get all notifications for current transaction\n     */\n    function getNotifications() internal view returns (Syscalls.Notification[] memory) {\n        return Syscalls.getNotifications();\n    }\n    \n    /**\n     * @dev Get notifications for specific contract\n     */\n    function getContractNotifications(address contractHash) \n        internal \n        view \n        returns (Syscalls.Notification[] memory) \n    {\n        return Syscalls.getNotifications(contractHash);\n    }\n    \n    // ========== Witness and Authorization ==========\n    \n    /**\n     * @dev Check witness for account\n     */\n    function checkWitness(address account) internal view returns (bool) {\n        return Syscalls.checkWitness(account);\n    }\n\n    /**\n     * @dev Check witness by public key\n     */\n    function checkWitness(bytes memory publicKey) internal view returns (bool) {\n        return Syscalls.checkWitness(publicKey);\n    }\n    \n    /**\n     * @dev Require witness or revert\n     */\n    function requireWitness(address account) internal view {\n        require(checkWitness(account), \"Runtime: invalid witness\");\n    }\n    \n    /**\n     * @dev Check multiple witnesses (OR logic)\n     */\n    function checkAnyWitness(address[] memory accounts) internal view returns (bool) {\n        for (uint256 i = 0; i < accounts.length; i++) {\n            if (checkWitness(accounts[i])) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    /**\n     * @dev Check multiple witnesses (AND logic)\n     */\n    function checkAllWitnesses(address[] memory accounts) internal view returns (bool) {\n        for (uint256 i = 0; i < accounts.length; i++) {\n            if (!checkWitness(accounts[i])) {\n                return false;\n            }\n        }\n        return true;\n    }\n    \n    /**\n     * @dev Multi-signature witness verification\n     */\n    function checkMultiSigWitness(\n        address[] memory signers,\n        uint256 threshold\n    ) internal view returns (bool) {\n        require(threshold > 0, \"Runtime: threshold must be positive\");\n        require(threshold <= signers.length, \"Runtime: threshold exceeds signers\");\n        \n        uint256 validWitnesses = 0;\n        \n        for (uint256 i = 0; i < signers.length; i++) {\n            address signer = signers[i];\n\n            // Prevent duplicate signers from satisfying quorum multiple times.\n            for (uint256 j = 0; j < i; j++) {\n                require(signers[j] != signer, \"Runtime: duplicate signer\");\n            }\n\n            if (checkWitness(signer)) {\n                validWitnesses++;\n                if (validWitnesses >= threshold) {\n                    return true;\n                }\n            }\n        }\n        \n        return false;\n    }\n    \n    // ========== Execution Context ==========\n    \n    /**\n     * @dev Get current execution context\n     */\n    function getExecutionContext() internal view returns (\n        address executingContract,\n        address callingContract,\n        address entryContract,\n        uint8 trigger,\n        uint256 gasLeft_,\n        uint256 invocationCounter\n    ) {\n        executingContract = Syscalls.getExecutingScriptHash();\n        callingContract = Syscalls.getCallingScriptHash();\n        entryContract = Syscalls.getEntryScriptHash();\n        trigger = Syscalls.getTrigger();\n        gasLeft_ = Syscalls.gasLeft();\n        invocationCounter = Syscalls.getInvocationCounter();\n    }\n\n    /**\n     * @dev Get current call flags\n     */\n    function getCallFlags() internal view returns (uint8) {\n        return Syscalls.getCallFlags();\n    }\n\n    /**\n     * @dev Get current script container\n     */\n    function getScriptContainer() internal view returns (Syscalls.Transaction memory) {\n        return Syscalls.getScriptContainer();\n    }\n\n    /**\n     * @dev Load script with arguments\n     */\n    function loadScript(bytes memory script, uint8 callFlags, bytes[] memory args) internal {\n        Syscalls.loadScript(script, callFlags, args);\n    }\n    \n    /**\n     * @dev Check execution trigger type\n     */\n    function getTriggerType() internal view returns (uint8) {\n        return Syscalls.getTrigger();\n    }\n    \n    /**\n     * @dev Check if in application trigger\n     */\n    function isApplicationTrigger() internal view returns (bool) {\n        return getTriggerType() == 0x40;\n    }\n\n    /**\n     * @dev Check if in verification trigger\n     */\n    function isVerificationTrigger() internal view returns (bool) {\n        return getTriggerType() == 0x20;\n    }\n    \n    // ========== Gas Management ==========\n    \n    /**\n     * @dev Get remaining gas\n     */\n    function gasLeft() internal view returns (uint256) {\n        return Syscalls.gasLeft();\n    }\n    \n    /**\n     * @dev Burn gas for optimization\n     */\n    function burnGas(uint256 amount) internal {\n        require(gasLeft() > amount, \"Runtime: insufficient gas to burn\");\n        Syscalls.burnGas(amount);\n    }\n    \n    /**\n     * @dev Placeholder for gas-optimized batch execution.\n     * @notice NeoVM does not support first-class function callbacks. This stub\n     *         exists to preserve API compatibility; it always reverts. Implement\n     *         batch logic inline at the call site instead.\n     */\n    function optimizeGasUsage(\n        function() internal /*batchOperation*/,\n        uint256 /*expectedSavings*/\n    ) internal {\n        revert(\"Runtime: optimizeGasUsage callback unsupported\");\n    }\n    \n    /**\n     * @dev Check if sufficient gas for operation\n     */\n    function hasSufficientGas(uint256 requiredGas) internal view returns (bool) {\n        return gasLeft() >= requiredGas;\n    }\n    \n    /**\n     * @dev Require minimum gas or revert\n     */\n    function requireGas(uint256 minimumGas) internal view {\n        require(hasSufficientGas(minimumGas), \"Runtime: insufficient gas\");\n    }\n    \n    // ========== Time and Block Operations ==========\n    \n    /**\n     * @dev Get current timestamp\n     */\n    function getTimestamp() internal view returns (uint256) {\n        return Syscalls.getTime();\n    }\n    \n    /**\n     * @dev Get current block index\n     */\n    function getBlockIndex() internal view returns (uint256) {\n        return Syscalls.getCurrentIndex();\n    }\n    \n    /**\n     * @dev Check if specific time has passed\n     */\n    function isAfterTime(uint256 timestamp) internal view returns (bool) {\n        return getTimestamp() > timestamp;\n    }\n    \n    /**\n     * @dev Check if specific block has passed\n     */\n    function isAfterBlock(uint256 blockIndex) internal view returns (bool) {\n        return getBlockIndex() > blockIndex;\n    }\n    \n    /**\n     * @dev Calculate time until block\n     */\n    function timeUntilBlock(uint256 targetBlock) internal view returns (uint256) {\n        uint256 currentBlock = getBlockIndex();\n        if (targetBlock <= currentBlock) return 0;\n        \n        uint256 blocksRemaining = targetBlock - currentBlock;\n        uint256 averageBlockTime = 15; // 15 seconds per block\n        return blocksRemaining * averageBlockTime;\n    }\n    \n    // ========== Logging and Debugging ==========\n    \n    /**\n     * @dev Log message to Neo logs\n     */\n    function log(string memory message) internal {\n        Syscalls.log(message);\n    }\n    \n    /**\n     * @dev Log with data\n     */\n    function logWithData(string memory message, bytes memory data) internal {\n        string memory fullMessage = string(abi.encodePacked(message, \": \", _bytesToHex(data)));\n        log(fullMessage);\n    }\n    \n    /**\n     * @dev Debug assertion\n     */\n    function assert(bool condition, string memory message) internal view {\n        if (!condition) {\n            revert(message);\n        }\n    }\n    \n    /**\n     * @dev Debug checkpoint\n     */\n    function checkpoint(string memory name) internal {\n        log(string(abi.encodePacked(\"CHECKPOINT: \", name, \" at block \", _uint256ToString(getBlockIndex()))));\n    }\n    \n    // ========== Error Handling ==========\n    \n    /**\n     * @dev Safe external call with error handling\n     */\n    function safeExternalCall(\n        address target,\n        bytes memory data\n    ) internal returns (bool success, bytes memory returnData) {\n        require(target != address(0), \"Runtime: call to zero address\");\n        target;\n        data;\n        log(\"External call failed: unsupported in standalone Runtime library; use Syscalls.contractCall\");\n        return (false, \"\");\n    }\n    \n    /**\n     * @dev Placeholder for external call wrapper.\n     * @notice Always reverts. Use `Syscalls.contractCall()` for inter-contract\n     *         calls on Neo N3.\n     */\n    function externalCall(address target, bytes memory data) external returns (bytes memory) {\n        target;\n        data;\n        revert(\"Runtime: external call unsupported; use Syscalls.contractCall\");\n    }\n    \n    // ========== Statistics and Monitoring ==========\n\n    /**\n     * @dev Get runtime statistics\n     */\n    function getStats() internal view returns (\n        uint256 currentBlock,\n        uint256 invocations\n    ) {\n        currentBlock = getBlockIndex();\n        invocations = Syscalls.getInvocationCounter();\n    }\n    \n    // ========== Utility Functions ==========\n    \n    /**\n     * @dev Convert bytes to hex string\n     */\n    function _bytesToHex(bytes memory data) private pure returns (string memory) {\n        bytes memory alphabet = \"0123456789abcdef\";\n        bytes memory str = new bytes(2 + data.length * 2);\n        str[0] = \"0\";\n        str[1] = \"x\";\n        \n        for (uint256 i = 0; i < data.length; i++) {\n            str[2 + i * 2] = alphabet[uint8(data[i] >> 4)];\n            str[3 + i * 2] = alphabet[uint8(data[i] & 0x0f)];\n        }\n        \n        return string(str);\n    }\n    \n    /**\n     * @dev Convert uint256 to string\n     */\n    function _uint256ToString(uint256 value) private pure returns (string memory) {\n        if (value == 0) {\n            return \"0\";\n        }\n        \n        uint256 temp = value;\n        uint256 digits;\n        \n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        \n        bytes memory buffer = new bytes(digits);\n        \n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        \n        return string(buffer);\n    }\n    \n    /**\n     * @dev Generate unique ID\n     */\n    function generateUniqueId() internal view returns (bytes32) {\n        return keccak256(abi.encode(\n            Syscalls.getExecutingScriptHash(),\n            getBlockIndex(),\n            getTimestamp(),\n            Syscalls.getInvocationCounter()\n        ));\n    }\n    \n    /**\n     * @dev Create deterministic random seed\n     */\n    function createRandomSeed(bytes memory entropy) internal view returns (uint256) {\n        return uint256(keccak256(abi.encode(\n            Syscalls.getCurrentRandom(),\n            entropy,\n            getTimestamp(),\n            getBlockIndex()\n        )));\n    }\n    \n    // ========== Performance Optimization ==========\n    \n    /**\n     * @dev Batch notifications for gas efficiency\n     */\n    function batchNotify(\n        string[] memory eventNames,\n        bytes[] memory data\n    ) internal {\n        require(eventNames.length == data.length, \"Runtime: array length mismatch\");\n        require(eventNames.length > 0, \"Runtime: empty arrays\");\n        require(eventNames.length <= 50, \"Runtime: too many notifications\");\n        \n        for (uint256 i = 0; i < eventNames.length; i++) {\n            notify(eventNames[i], data[i]);\n        }\n    }\n    \n    /**\n     * @dev Placeholder for conditional gas-gated execution.\n     * @notice NeoVM does not support first-class function callbacks. This stub\n     *         always reverts. Use `gasLeft()` checks inline instead.\n     */\n    function executeIfGasAvailable(\n        uint256 /*requiredGas*/,\n        function() internal /*operation*/\n    ) internal {\n        revert(\"Runtime: executeIfGasAvailable callback unsupported\");\n    }\n\n    /**\n     * @dev Placeholder for gas-budgeted loop execution.\n     * @notice NeoVM does not support first-class function callbacks. This stub\n     *         always reverts. Use a standard `for` loop with `gasLeft()` guards.\n     */\n    function optimizedLoop(\n        uint256 /*iterations*/,\n        uint256 /*gasPerIteration*/,\n        function(uint256) internal /*loopBody*/\n    ) internal {\n        revert(\"Runtime: optimizedLoop callback unsupported\");\n    }\n    \n    // ========== Access Control Integration ==========\n    \n    /**\n     * @dev Role-based access control\n     * @notice Neo N3 RoleManagement does not expose a generic hasRole method.\n     *         This falls back to witness verification. For role-specific checks,\n     *         use NativeCalls.getDesignatedByRole() directly.\n     */\n    function hasRole(address account, bytes32 role) internal view returns (bool) {\n        // Neo N3 RoleManagement only supports getDesignatedByRole/designateAsRole,\n        // not arbitrary role checks. Fall back to witness verification.\n        role; // silence unused parameter warning\n        return checkWitness(account);\n    }\n    \n    /**\n     * @dev Committee member check\n     */\n    function isCommitteeMember(address account) internal view returns (bool) {\n        return NativeCalls.isCommittee(account);\n    }\n    \n    /**\n     * @dev Validator check\n     */\n    function isValidator(address account) internal view returns (bool) {\n        address[] memory validators = NativeCalls.getNextBlockValidators();\n        for (uint256 i = 0; i < validators.length; i++) {\n            if (validators[i] == account) {\n                return true;\n            }\n        }\n        return false;\n    }\n    \n    // ========== Oracle Integration ==========\n    \n    /**\n     * @dev Handle oracle response\n     */\n    function handleOracleResponse(\n        string memory url,\n        bytes memory userData,\n        uint256 code,\n        bytes memory result\n    ) internal {\n        require(msg.sender == getOracleContract(), \"Runtime: unauthorized oracle response\");\n        \n        // Process oracle response\n        if (code == 0) {\n            // Success\n            notify(\"OracleResponse\", abi.encode(url, result, userData));\n        } else {\n            // Error\n            notify(\"OracleError\", abi.encode(url, code, userData));\n        }\n    }\n    \n    /**\n     * @dev Get oracle contract address\n     */\n    function getOracleContract() internal pure returns (address) {\n        return 0xfe924b7cfe89ddd271abaf7210a80a7e11178758; // Oracle contract hash\n    }\n    \n    // ========== Error Recovery ==========\n    \n    /**\n     * @dev Placeholder for try/fallback pattern.\n     * @notice NeoVM does not support first-class function callbacks. This stub\n     *         always reverts. Use Solidity `try/catch` blocks instead.\n     */\n    function tryWithFallback(\n        function() internal /*primaryOperation*/,\n        function() internal /*fallbackOperation*/\n    ) internal {\n        revert(\"Runtime: tryWithFallback callback unsupported\");\n    }\n\n    /**\n     * @dev Placeholder for standalone primary execution.\n     * @notice Always reverts. Use Solidity `try/catch` for error recovery.\n     */\n    function executePrimary(function() internal /*operation*/) internal {\n        revert(\"Runtime: executePrimary unsupported in standalone mode\");\n    }\n    \n    /**\n     * @dev Placeholder for graceful degradation under gas pressure.\n     * @notice NeoVM does not support first-class function callbacks. This stub\n     *         always reverts. Use `gasLeft()` checks with if/else branching.\n     */\n    function degradeGracefully(\n        function() internal /*fullOperation*/,\n        function() internal /*limitedOperation*/,\n        uint256 /*fullOperationGas*/\n    ) internal {\n        revert(\"Runtime: degradeGracefully callback unsupported\");\n    }\n    \n    // ========== Platform Integration ==========\n    \n    /**\n     * @dev Get platform information\n     */\n    function getPlatformInfo() internal view returns (\n        string memory platform,\n        uint32 network,\n        uint8 addressVersion\n    ) {\n        platform = Syscalls.getPlatform();\n        network = Syscalls.getNetwork();\n        addressVersion = Syscalls.getAddressVersion();\n    }\n    \n    /**\n     * @dev Check if running on specific network\n     */\n    function isMainNet() internal view returns (bool) {\n        return Syscalls.getNetwork() == 860833102; // Neo N3 MainNet\n    }\n    \n    function isTestNet() internal view returns (bool) {\n        return Syscalls.getNetwork() == 894710606; // Neo N3 TestNet\n    }\n    \n    /**\n     * @dev Get invocation counter\n     */\n    function getInvocationCounter() internal view returns (uint256) {\n        return Syscalls.getInvocationCounter();\n    }\n\n    /**\n     * @dev Get current transaction signers\n     */\n    function getCurrentSigners() internal view returns (Syscalls.Signer[] memory) {\n        return Syscalls.getCurrentSigners();\n    }\n    \n    // ========== Advanced Runtime Features ==========\n    \n    /**\n     * @dev Create execution checkpoint\n     */\n    function createCheckpoint(string memory name, bytes memory state) internal {\n        bytes32 checkpointId = keccak256(abi.encode(name, getTimestamp()));\n        \n        notify(\"Checkpoint\", abi.encode(\n            checkpointId,\n            name,\n            state,\n            getBlockIndex(),\n            getTimestamp(),\n            gasLeft()\n        ));\n    }\n    \n    /**\n     * @dev Placeholder for execution measurement.\n     * @notice NeoVM does not support first-class function callbacks. This stub\n     *         always reverts. Use `gasLeft()` before/after to measure cost.\n     */\n    function measureExecution(\n        function() internal /*operation*/,\n        string memory /*operationName*/\n    ) internal {\n        revert(\"Runtime: measureExecution callback unsupported\");\n    }\n    \n    /**\n     * @dev Emergency runtime stop\n     */\n    function emergencyStop(string memory reason) internal {\n        notify(\"EmergencyStop\", abi.encode(\n            Syscalls.getExecutingScriptHash(),\n            reason,\n            getTimestamp(),\n            gasLeft()\n        ));\n        \n        // Log critical information\n        log(string(abi.encodePacked(\"EMERGENCY STOP: \", reason)));\n        \n        revert(reason);\n    }\n}\n"
    },
    "libraries/Storage.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title Neo N3 Storage Library\n * @dev Advanced storage operations for Neo N3 blockchain\n * @author Jimmy <jimmy@r3e.network>\n * \n * This library provides enhanced storage capabilities:\n * - Context-aware storage operations\n * - Iterator support for range queries\n * - Batch operations for efficiency\n * - Storage usage tracking\n * - Advanced key management\n */\n\nimport \"../contracts/Syscalls.sol\";\nimport \"../contracts/NativeCalls.sol\";\nimport \"./Runtime.sol\";\n\nlibrary Storage {\n    using Syscalls for *;\n    \n    // Events for storage operations\n    event StorageInitialized(address indexed contract_);\n    event StorageOperation(string indexed operation, bytes key, uint256 size);\n    event BatchStorageOperation(uint256 operations, uint256 totalSize);\n    \n    // ========== Context ==========\n\n    /**\n     * @dev Get current storage context\n     */\n    function getContext() internal view returns (Syscalls.StorageContext memory) {\n        return Syscalls.getStorageContext();\n    }\n    \n    /**\n     * @dev Get read-only storage context\n     */\n    function getReadOnlyContext() internal view returns (Syscalls.StorageContext memory) {\n        return Syscalls.getReadOnlyStorageContext();\n    }\n\n    /**\n     * @dev Convert storage context to read-only\n     */\n    function asReadOnly(Syscalls.StorageContext memory context)\n        internal\n        view\n        returns (Syscalls.StorageContext memory)\n    {\n        return Syscalls.storageAsReadOnly(context);\n    }\n    \n    // ========== Basic Storage Operations ==========\n    \n    /**\n     * @dev Store value by key\n     */\n    function put(bytes memory key, bytes memory value) internal {\n        Syscalls.StorageContext memory context = getContext();\n        Syscalls.storagePut(context, key, value);\n\n        emit StorageOperation(\"PUT\", key, value.length);\n    }\n    \n    /**\n     * @dev Get value by key\n     */\n    function get(bytes memory key) internal view returns (bytes memory) {\n        Syscalls.StorageContext memory context = getReadOnlyContext();\n        return Syscalls.storageGet(context, key);\n    }\n    \n    /**\n     * @dev Remove value by key\n     */\n    function remove(bytes memory key) internal {\n        Syscalls.StorageContext memory context = getContext();\n        Syscalls.storageDelete(context, key);\n\n        emit StorageOperation(\"DELETE\", key, 0);\n    }\n    \n    /**\n     * @dev Check if key exists\n     */\n    function exists(bytes memory key) internal view returns (bool) {\n        bytes memory value = get(key);\n        return value.length > 0;\n    }\n\n    // ========== Local Storage Operations ==========\n\n    /**\n     * @dev Store value by key (local context)\n     */\n    function putLocal(bytes memory key, bytes memory value) internal {\n        Syscalls.storagePutLocal(key, value);\n\n        emit StorageOperation(\"PUT_LOCAL\", key, value.length);\n    }\n\n    /**\n     * @dev Get value by key (local context)\n     */\n    function getLocal(bytes memory key) internal view returns (bytes memory) {\n        return Syscalls.storageGetLocal(key);\n    }\n\n    /**\n     * @dev Remove value by key (local context)\n     */\n    function removeLocal(bytes memory key) internal {\n        Syscalls.storageDeleteLocal(key);\n\n        emit StorageOperation(\"DELETE_LOCAL\", key, 0);\n    }\n    \n    // ========== Iterator Operations ==========\n    \n    /**\n     * @dev Find all keys with prefix\n     */\n    function find(bytes memory prefix) internal view returns (Iterator memory) {\n        Syscalls.StorageContext memory context = getReadOnlyContext();\n        return Syscalls.storageFind(context, prefix);\n    }\n\n    /**\n     * @dev Find all keys with prefix (local context)\n     */\n    function findLocal(bytes memory prefix) internal view returns (Iterator memory) {\n        return Syscalls.storageFindLocal(prefix);\n    }\n    \n    /**\n     * @dev Get all values with prefix\n     */\n    function findValues(bytes memory prefix) internal view returns (bytes[] memory values) {\n        Iterator memory iterator = find(prefix);\n        bytes[] memory temp = new bytes[](1000);\n        uint256 count = 0;\n\n        while (iterator.next() && count < 1000) {\n            temp[count] = iterator.value();\n            count++;\n        }\n\n        values = new bytes[](count);\n        for (uint256 i = 0; i < count; i++) {\n            values[i] = temp[i];\n        }\n    }\n\n    /**\n     * @dev Get all values with prefix (local context)\n     */\n    function findLocalValues(bytes memory prefix) internal view returns (bytes[] memory values) {\n        Iterator memory iterator = findLocal(prefix);\n        bytes[] memory temp = new bytes[](1000);\n        uint256 count = 0;\n\n        while (iterator.next() && count < 1000) {\n            temp[count] = iterator.value();\n            count++;\n        }\n\n        values = new bytes[](count);\n        for (uint256 i = 0; i < count; i++) {\n            values[i] = temp[i];\n        }\n    }\n    \n    /**\n     * @dev Get all keys with prefix\n     */\n    function findKeys(bytes memory prefix) internal view returns (bytes[] memory keys) {\n        Iterator memory iterator = find(prefix);\n        bytes[] memory temp = new bytes[](1000);\n        uint256 count = 0;\n\n        while (iterator.next() && count < 1000) {\n            temp[count] = iterator.currentKey;\n            count++;\n        }\n\n        keys = new bytes[](count);\n        for (uint256 i = 0; i < count; i++) {\n            keys[i] = temp[i];\n        }\n    }\n\n    /**\n     * @dev Get all keys with prefix (local context)\n     */\n    function findLocalKeys(bytes memory prefix) internal view returns (bytes[] memory keys) {\n        Iterator memory iterator = findLocal(prefix);\n        bytes[] memory temp = new bytes[](1000);\n        uint256 count = 0;\n\n        while (iterator.next() && count < 1000) {\n            temp[count] = iterator.currentKey;\n            count++;\n        }\n\n        keys = new bytes[](count);\n        for (uint256 i = 0; i < count; i++) {\n            keys[i] = temp[i];\n        }\n    }\n    \n    /**\n     * @dev Count entries with prefix\n     */\n    function count(bytes memory prefix) internal view returns (uint256) {\n        Iterator memory iterator = find(prefix);\n        uint256 total = 0;\n        \n        while (iterator.next()) {\n            total++;\n        }\n        \n        return total;\n    }\n\n    /**\n     * @dev Count entries with prefix (local context)\n     */\n    function countLocal(bytes memory prefix) internal view returns (uint256) {\n        Iterator memory iterator = findLocal(prefix);\n        uint256 total = 0;\n\n        while (iterator.next()) {\n            total++;\n        }\n\n        return total;\n    }\n    \n    // ========== Batch Operations ==========\n    \n    /**\n     * @dev Batch put operations\n     */\n    function batchPut(bytes[] memory keys, bytes[] memory values) internal {\n        require(keys.length == values.length, \"Storage: array length mismatch\");\n        require(keys.length > 0, \"Storage: empty arrays\");\n        require(keys.length <= 100, \"Storage: too many operations\");\n        \n        uint256 totalSize = 0;\n        \n        for (uint256 i = 0; i < keys.length; i++) {\n            put(keys[i], values[i]);\n            totalSize += values[i].length;\n        }\n        \n        emit BatchStorageOperation(keys.length, totalSize);\n    }\n    \n    /**\n     * @dev Batch get operations\n     */\n    function batchGet(bytes[] memory keys) internal view returns (bytes[] memory values) {\n        require(keys.length > 0, \"Storage: empty array\");\n        require(keys.length <= 100, \"Storage: too many operations\");\n        \n        values = new bytes[](keys.length);\n        \n        for (uint256 i = 0; i < keys.length; i++) {\n            values[i] = get(keys[i]);\n        }\n    }\n    \n    /**\n     * @dev Batch delete operations\n     */\n    function batchDelete(bytes[] memory keys) internal {\n        require(keys.length > 0, \"Storage: empty array\");\n        require(keys.length <= 100, \"Storage: too many operations\");\n        \n        for (uint256 i = 0; i < keys.length; i++) {\n            remove(keys[i]);\n        }\n        \n        emit BatchStorageOperation(keys.length, 0);\n    }\n    \n    // ========== Advanced Key Management ==========\n    \n    /**\n     * @dev Generate Solidity-compatible mapping key\n     */\n    function generateMappingKey(bytes memory slot, bytes memory key) internal pure returns (bytes memory) {\n        return abi.encode(keccak256(abi.encode(key, slot)));\n    }\n    \n    /**\n     * @dev Generate array element key\n     */\n    function generateArrayKey(bytes memory slot, uint256 index) internal pure returns (bytes memory) {\n        bytes32 baseSlot = keccak256(slot);\n        return abi.encode(bytes32(uint256(baseSlot) + index));\n    }\n    \n    /**\n     * @dev Generate nested mapping key\n     */\n    function generateNestedMappingKey(\n        bytes memory slot,\n        bytes memory key1,\n        bytes memory key2\n    ) internal pure returns (bytes memory) {\n        bytes32 innerSlot = keccak256(abi.encode(key1, slot));\n        return abi.encode(keccak256(abi.encode(key2, innerSlot)));\n    }\n    \n    /**\n     * @dev Generate prefixed key\n     */\n    function prefixKey(string memory prefix, bytes memory key) internal pure returns (bytes memory) {\n        return abi.encodePacked(prefix, key);\n    }\n    \n    // ========== Storage Patterns ==========\n    \n    /**\n     * @dev Store mapping value (Solidity mapping compatibility)\n     */\n    function setMapping(\n        bytes memory slot,\n        bytes memory key,\n        bytes memory value\n    ) internal {\n        bytes memory storageKey = generateMappingKey(slot, key);\n        put(storageKey, value);\n    }\n    \n    /**\n     * @dev Get mapping value\n     */\n    function getMapping(bytes memory slot, bytes memory key) internal view returns (bytes memory) {\n        bytes memory storageKey = generateMappingKey(slot, key);\n        return get(storageKey);\n    }\n    \n    /**\n     * @dev Store array element\n     */\n    function setArrayElement(\n        bytes memory slot,\n        uint256 index,\n        bytes memory value\n    ) internal {\n        bytes memory storageKey = generateArrayKey(slot, index);\n        put(storageKey, value);\n    }\n    \n    /**\n     * @dev Get array element\n     */\n    function getArrayElement(bytes memory slot, uint256 index) internal view returns (bytes memory) {\n        bytes memory storageKey = generateArrayKey(slot, index);\n        return get(storageKey);\n    }\n    \n    /**\n     * @dev Store array length\n     */\n    function setArrayLength(bytes memory slot, uint256 length) internal {\n        put(slot, abi.encode(length));\n    }\n    \n    /**\n     * @dev Get array length\n     */\n    function getArrayLength(bytes memory slot) internal view returns (uint256) {\n        bytes memory data = get(slot);\n        if (data.length == 0) return 0;\n        return abi.decode(data, (uint256));\n    }\n    \n    // ========== Storage Analytics ==========\n\n    /**\n     * @dev Estimate storage cost for operation\n     */\n    function estimateCost(uint256 dataSize) internal view returns (uint256) {\n        uint256 storagePrice = NativeCalls.getStoragePrice();\n        return dataSize * storagePrice;\n    }\n    \n    // ========== Utility Functions ==========\n    \n    /**\n     * @dev Clear all storage with prefix (expensive operation)\n     */\n    function clearPrefix(bytes memory prefix) internal {\n        bytes[] memory keys = findKeys(prefix);\n        uint256 i = 0;\n        while (i < keys.length) {\n            // Calculate batch size (max 100)\n            uint256 batchSize = keys.length - i;\n            if (batchSize > 100) {\n                batchSize = 100;\n            }\n            // Create batch\n            bytes[] memory batch = new bytes[](batchSize);\n            for (uint256 j = 0; j < batchSize; j++) {\n                batch[j] = keys[i + j];\n            }\n            batchDelete(batch);\n            i += batchSize;\n        }\n    }\n    \n    /**\n     * @dev Copy storage range\n     */\n    function copyRange(\n        bytes memory sourcePrefix,\n        bytes memory targetPrefix\n    ) internal {\n        bytes[] memory keys = findKeys(sourcePrefix);\n        bytes[] memory values = findValues(sourcePrefix);\n        \n        require(keys.length == values.length, \"Storage: data corruption\");\n        \n        bytes[] memory newKeys = new bytes[](keys.length);\n        \n        for (uint256 i = 0; i < keys.length; i++) {\n            // Replace prefix\n            newKeys[i] = abi.encodePacked(targetPrefix, keys[i][sourcePrefix.length:]);\n        }\n        \n        batchPut(newKeys, values);\n    }\n    \n    /**\n     * @dev Validate storage key format\n     */\n    function isValidKey(bytes memory key) internal pure returns (bool) {\n        return key.length > 0 && key.length <= 64; // Neo storage key limit\n    }\n    \n    /**\n     * @dev Compress storage value using RLE compression\n     */\n    function compress(bytes memory data) internal pure returns (bytes memory) {\n        if (data.length < 4) {\n            return data; // Too small to compress effectively\n        }\n        \n        // Run-length encoding compression\n        bytes memory compressed = new bytes(data.length * 2); // Worst case size\n        uint256 compressedIndex = 0;\n        uint256 i = 0;\n        \n        while (i < data.length) {\n            bytes1 currentByte = data[i];\n            uint256 runLength = 1;\n            \n            // Count consecutive identical bytes\n            while (i + runLength < data.length && data[i + runLength] == currentByte && runLength < 255) {\n                runLength++;\n            }\n            \n            // Store run-length encoded data\n            if (runLength >= 4 || currentByte == 0x00 || currentByte == 0xFF) {\n                // Use RLE for runs of 4+ or zeros\n                compressed[compressedIndex++] = 0xFF; // Escape byte\n                compressed[compressedIndex++] = bytes1(uint8(runLength));\n                compressed[compressedIndex++] = currentByte;\n            } else {\n                // Store literal bytes\n                for (uint256 j = 0; j < runLength; j++) {\n                    compressed[compressedIndex++] = currentByte;\n                }\n            }\n            \n            i += runLength;\n        }\n        \n        // Resize to actual compressed size\n        bytes memory result = new bytes(compressedIndex);\n        for (uint256 k = 0; k < compressedIndex; k++) {\n            result[k] = compressed[k];\n        }\n        \n        return result;\n    }\n    \n    /**\n     * @dev Decompress RLE-compressed storage value\n     */\n    function decompress(bytes memory compressedData) internal pure returns (bytes memory) {\n        if (compressedData.length == 0) {\n            return compressedData;\n        }\n        \n        // Estimate maximum decompressed size\n        bytes memory decompressed = new bytes(compressedData.length * 255); // Worst case\n        uint256 decompressedIndex = 0;\n        uint256 i = 0;\n        \n        while (i < compressedData.length) {\n            if (compressedData[i] == 0xFF && i + 2 < compressedData.length) {\n                // RLE sequence\n                uint256 runLength = uint8(compressedData[i + 1]);\n                bytes1 value = compressedData[i + 2];\n                \n                for (uint256 j = 0; j < runLength; j++) {\n                    decompressed[decompressedIndex++] = value;\n                }\n                \n                i += 3;\n            } else {\n                // Literal byte\n                decompressed[decompressedIndex++] = compressedData[i];\n                i++;\n            }\n        }\n        \n        // Resize to actual decompressed size\n        bytes memory result = new bytes(decompressedIndex);\n        for (uint256 k = 0; k < decompressedIndex; k++) {\n            result[k] = decompressed[k];\n        }\n        \n        return result;\n    }\n    \n    // ========== Advanced Storage Patterns ==========\n    \n    /**\n     * @dev Atomic storage update\n     */\n    function atomicUpdate(\n        bytes memory /*key*/,\n        function(bytes memory) internal pure returns (bytes memory) /*updateFunction*/\n    ) internal {\n        revert(\"Storage: atomicUpdate callback unsupported\");\n    }\n    \n    /**\n     * @dev Conditional storage update\n     */\n    function conditionalPut(\n        bytes memory /*key*/,\n        bytes memory /*value*/,\n        function(bytes memory) internal pure returns (bool) /*condition*/\n    ) internal returns (bool) {\n        revert(\"Storage: conditionalPut callback unsupported\");\n    }\n    \n    /**\n     * @dev Store with expiration (using block height)\n     */\n    function putWithExpiration(\n        bytes memory key,\n        bytes memory value,\n        uint256 expirationBlock\n    ) internal {\n        bytes memory wrappedValue = abi.encode(value, expirationBlock);\n        put(key, wrappedValue);\n    }\n    \n    /**\n     * @dev Get value with expiration check\n     */\n    function getWithExpiration(bytes memory key) internal view returns (bytes memory) {\n        bytes memory wrappedValue = get(key);\n        if (wrappedValue.length == 0) return \"\";\n        \n        (bytes memory value, uint256 expirationBlock) = abi.decode(wrappedValue, (bytes, uint256));\n        \n        if (block.number > expirationBlock) {\n            return \"\"; // Expired\n        }\n        \n        return value;\n    }\n    \n    /**\n     * @dev Clean expired entries\n     */\n    function cleanExpired(bytes memory prefix) internal {\n        Iterator memory iterator = find(prefix);\n        bytes[] memory expiredKeys = new bytes[](100);\n        uint256 expiredCount = 0;\n        \n        while (iterator.next() && expiredCount < 100) {\n            bytes memory value = iterator.value();\n            if (value.length >= 32) {\n                (, uint256 expirationBlock) = abi.decode(value, (bytes, uint256));\n                if (block.number > expirationBlock) {\n                    expiredKeys[expiredCount] = iterator.currentKey;\n                    expiredCount++;\n                }\n            }\n        }\n        \n        if (expiredCount > 0) {\n            bytes[] memory trimmed = new bytes[](expiredCount);\n            for (uint256 i = 0; i < expiredCount; i++) {\n                trimmed[i] = expiredKeys[i];\n            }\n            batchDelete(trimmed);\n        }\n    }\n    \n    // ========== Storage Optimization ==========\n    \n    /**\n     * @dev Pack multiple values into single storage slot\n     */\n    function packValues(bytes[] memory values) internal pure returns (bytes memory) {\n        return abi.encode(values);\n    }\n    \n    /**\n     * @dev Unpack multiple values from single storage slot\n     */\n    function unpackValues(bytes memory packedData) internal pure returns (bytes[] memory) {\n        return abi.decode(packedData, (bytes[]));\n    }\n    \n    /**\n     * @dev Store packed values\n     */\n    function putPacked(bytes memory key, bytes[] memory values) internal {\n        bytes memory packedData = packValues(values);\n        put(key, packedData);\n    }\n    \n    /**\n     * @dev Get unpacked values\n     */\n    function getPacked(bytes memory key) internal view returns (bytes[] memory) {\n        bytes memory packedData = get(key);\n        if (packedData.length == 0) {\n            return new bytes[](0);\n        }\n        return unpackValues(packedData);\n    }\n    \n    // ========== Specialized Storage Types ==========\n    \n    /**\n     * @dev Store uint256 value\n     */\n    function putUint256(bytes memory key, uint256 value) internal {\n        put(key, abi.encode(value));\n    }\n    \n    /**\n     * @dev Get uint256 value\n     */\n    function getUint256(bytes memory key) internal view returns (uint256) {\n        bytes memory data = get(key);\n        if (data.length == 0) return 0;\n        return abi.decode(data, (uint256));\n    }\n    \n    /**\n     * @dev Store address value\n     */\n    function putAddress(bytes memory key, address value) internal {\n        put(key, abi.encode(value));\n    }\n    \n    /**\n     * @dev Get address value\n     */\n    function getAddress(bytes memory key) internal view returns (address) {\n        bytes memory data = get(key);\n        if (data.length == 0) return address(0);\n        return abi.decode(data, (address));\n    }\n    \n    /**\n     * @dev Store string value\n     */\n    function putString(bytes memory key, string memory value) internal {\n        put(key, bytes(value));\n    }\n    \n    /**\n     * @dev Get string value\n     */\n    function getString(bytes memory key) internal view returns (string memory) {\n        bytes memory data = get(key);\n        return string(data);\n    }\n    \n    /**\n     * @dev Store boolean value\n     */\n    function putBool(bytes memory key, bool value) internal {\n        put(key, abi.encode(value));\n    }\n    \n    /**\n     * @dev Get boolean value\n     */\n    function getBool(bytes memory key) internal view returns (bool) {\n        bytes memory data = get(key);\n        if (data.length == 0) return false;\n        return abi.decode(data, (bool));\n    }\n    \n    // ========== Storage Security ==========\n    \n    /**\n     * @dev Secure storage with checksum\n     */\n    function putSecure(bytes memory key, bytes memory value) internal {\n        bytes32 checksum = keccak256(value);\n        bytes memory secureValue = abi.encode(value, checksum);\n        put(key, secureValue);\n    }\n    \n    /**\n     * @dev Get secure storage with validation\n     */\n    function getSecure(bytes memory key) internal view returns (bytes memory) {\n        bytes memory secureValue = get(key);\n        if (secureValue.length == 0) return \"\";\n        \n        (bytes memory value, bytes32 checksum) = abi.decode(secureValue, (bytes, bytes32));\n        \n        require(keccak256(value) == checksum, \"Storage: data corruption detected\");\n        return value;\n    }\n    \n    /**\n     * @dev Access control for storage keys\n     */\n    function putWithAccess(\n        bytes memory key,\n        bytes memory value,\n        address requiredSigner\n    ) internal {\n        require(Runtime.checkWitness(requiredSigner), \"Storage: unauthorized access\");\n        put(key, value);\n    }\n    \n    // ========== Storage Migration ==========\n    \n    /**\n     * @dev Migrate storage from old key format to new\n     */\n    function migrateKeys(\n        bytes memory /*oldPrefix*/,\n        bytes memory /*newPrefix*/,\n        function(bytes memory) internal pure returns (bytes memory) /*keyTransform*/\n    ) internal {\n        revert(\"Storage: migrateKeys callback unsupported\");\n    }\n    \n    /**\n     * @dev Backup storage range\n     */\n    function backup(bytes memory prefix, bytes memory backupPrefix) internal {\n        copyRange(prefix, backupPrefix);\n    }\n    \n    /**\n     * @dev Restore storage from backup\n     */\n    function restore(bytes memory backupPrefix, bytes memory targetPrefix) internal {\n        copyRange(backupPrefix, targetPrefix);\n    }\n    \n    // ========== Neo-Specific Extensions ==========\n    \n    /**\n     * @dev Store with Neo-compatible key encoding\n     */\n    function putNeoKey(bytes20 key, bytes memory value) internal {\n        put(abi.encode(key), value);\n    }\n    \n    /**\n     * @dev Get with Neo-compatible key encoding\n     */\n    function getNeoKey(bytes20 key) internal view returns (bytes memory) {\n        return get(abi.encode(key));\n    }\n    \n    /**\n     * @dev Store contract metadata\n     */\n    function putContractMetadata(\n        string memory name,\n        string memory version,\n        string memory author,\n        bytes memory extra\n    ) internal {\n        bytes memory metadata = abi.encode(name, version, author, extra, block.timestamp);\n        put(\"__CONTRACT_METADATA__\", metadata);\n    }\n    \n    /**\n     * @dev Get contract metadata\n     */\n    function getContractMetadata() internal view returns (\n        string memory name,\n        string memory version,\n        string memory author,\n        bytes memory extra,\n        uint256 timestamp\n    ) {\n        bytes memory metadata = get(\"__CONTRACT_METADATA__\");\n        if (metadata.length == 0) {\n            name = \"\";\n            version = \"\";\n            author = \"\";\n            extra = new bytes(0);\n            timestamp = 0;\n            return (name, version, author, extra, timestamp);\n        }\n        (name, version, author, extra, timestamp) = abi.decode(metadata, (string, string, string, bytes, uint256));\n        return (name, version, author, extra, timestamp);\n    }\n}\n"
    },
    "standards/NEP17.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title NEP-17 Fungible Token Standard\n * @dev Complete implementation of Neo N3 NEP-17 standard for Solidity\n * @author Jimmy <jimmy@r3e.network>\n * \n * NEP-17 is Neo's enhanced fungible token standard, providing:\n * - Standard ERC-20 compatibility\n * - Neo-specific features (onNEP17Payment callback)\n * - Advanced transfer capabilities\n * - Integration with Neo native tokens\n * - Event system compatible with Neo Runtime.Notify\n */\n\nimport \"../contracts/FrameworkBase.sol\";\nimport \"../libraries/Neo.sol\";\nimport \"../libraries/Runtime.sol\";\nimport \"../libraries/Storage.sol\";\n\n/// @dev Neo N3 Any type - represents any stack item type in NeoVM\ntype Any is bytes;\n\n/**\n * @title INEP17\n * @dev Interface for NEP-17 fungible token standard\n */\ninterface INEP17 {\n    // Standard NEP-17 functions\n    function symbol() external view returns (string memory);\n    function decimals() external view returns (uint8);\n    function totalSupply() external view returns (uint256);\n    function balanceOf(address account) external view returns (uint256);\n    // NEP-17 `data` is an unconstrained StackItem (Neo ABI type: Any).\n    // This devpack uses the Neo DevPack for Solidity `Any` type to accurately reflect the standard.\n    function transfer(address from, address to, uint256 amount, Any calldata data) external returns (bool);\n    \n    // Events\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n}\n\n/**\n * @title INEP17Receiver\n * @dev Interface for contracts that can receive NEP-17 tokens\n */\ninterface INEP17Receiver {\n    function onNEP17Payment(address from, uint256 amount, Any calldata data) external;\n}\n\n/**\n * @title NEP17\n * @dev Complete NEP-17 token implementation with Neo N3 integration\n */\ncontract NEP17 is INEP17, FrameworkBase {\n    using Neo for *;\n    using Runtime for *;\n\n    // Neo N3 Oracle native contract hash.\n    address private constant ORACLE_NATIVE_CONTRACT = 0xfe924b7cfe89ddd271abaf7210a80a7e11178758;\n    \n    // Token metadata\n    string private _name;\n    string private _symbol;\n    uint8 private _decimals;\n    uint256 private _totalSupply;\n    \n    // Balances and allowances\n    mapping(address => uint256) private _balances;\n    mapping(address => mapping(address => uint256)) private _allowances;\n    \n    // NEP-17 specific features\n    bool private _transfersEnabled = true;\n    address private _minter;\n    uint256 private _maxSupply;\n    uint256 private _conditionalTransferNonce;\n    \n    // Events (NEP-17 compatible)\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n    event Mint(address indexed to, uint256 amount);\n    event Burn(address indexed from, uint256 amount);\n    \n    // NEP-17 specific events\n    event TransfersEnabled();\n    event TransfersDisabled();\n    event MinterChanged(address indexed oldMinter, address indexed newMinter);\n    event MaxSupplySet(uint256 maxSupply);\n\n    // Extended events\n    event EmergencyPause(address indexed caller, uint256 timestamp);\n    event EmergencyUnpause(address indexed caller, uint256 timestamp);\n    event TimelockCreated(\n        bytes32 indexed timelockId,\n        address indexed from,\n        address indexed to,\n        uint256 amount,\n        uint256 releaseTime\n    );\n    event TimelockClaimed(bytes32 indexed timelockId, address indexed to, uint256 amount);\n    event ConditionalTransferCreated(\n        bytes32 indexed requestId,\n        address indexed from,\n        address indexed to,\n        uint256 amount\n    );\n    event ConditionalTransferExecuted(address indexed from, address indexed to, uint256 amount);\n    event ConditionalTransferFailed(address indexed from, uint256 amount);\n    \n    // Custom errors\n    error NEP17InsufficientBalance(address account, uint256 balance, uint256 needed);\n    error NEP17InvalidReceiver(address receiver);\n    error NEP17TransfersDisabled();\n    error NEP17ExceedsMaxSupply(uint256 amount, uint256 maxSupply);\n    error NEP17InvalidAmount(uint256 amount);\n    error NEP17NotMinter(address caller);\n    \n    // Modifiers\n    modifier whenTransfersEnabled() {\n        if (!_transfersEnabled) revert NEP17TransfersDisabled();\n        _;\n    }\n    \n    modifier onlyMinter() {\n        if (msg.sender != _minter) revert NEP17NotMinter(msg.sender);\n        _;\n    }\n    \n    modifier validAmount(uint256 amount) {\n        if (amount == 0) revert NEP17InvalidAmount(amount);\n        _;\n    }\n    \n    modifier validReceiver(address to) {\n        if (to == address(0)) revert NEP17InvalidReceiver(to);\n        _;\n    }\n    \n    /**\n     * @dev Constructor\n     */\n    constructor(\n        string memory name_,\n        string memory symbol_,\n        uint8 decimals_,\n        uint256 initialSupply,\n        uint256 maxSupply_\n    ) FrameworkBase() {\n        require(bytes(name_).length > 0, \"NEP17: name cannot be empty\");\n        require(bytes(symbol_).length > 0, \"NEP17: symbol cannot be empty\");\n        require(decimals_ <= 18, \"NEP17: decimals cannot exceed 18\");\n        \n        _name = name_;\n        _symbol = symbol_;\n        _decimals = decimals_;\n        _minter = msg.sender;\n        _maxSupply = maxSupply_;\n        \n        if (initialSupply > 0) {\n            _mint(msg.sender, initialSupply);\n        }\n    }\n    \n    // ========== View Functions ==========\n    \n    /**\n     * @dev Returns the name of the token\n     */\n    function name() public view returns (string memory) {\n        return _name;\n    }\n    \n    /**\n     * @dev Returns the symbol of the token\n     */\n    function symbol() public view override returns (string memory) {\n        return _symbol;\n    }\n    \n    /**\n     * @dev Returns the number of decimals\n     */\n    function decimals() public view override returns (uint8) {\n        return _decimals;\n    }\n    \n    /**\n     * @dev Returns the total supply\n     */\n    function totalSupply() public view override returns (uint256) {\n        return _totalSupply;\n    }\n    \n    /**\n     * @dev Returns the balance of an account\n     */\n    function balanceOf(address account) public view override returns (uint256) {\n        return _balances[account];\n    }\n    \n    /**\n     * @dev Returns the allowance\n     */\n    function allowance(address owner, address spender) public view returns (uint256) {\n        return _allowances[owner][spender];\n    }\n    \n    /**\n     * @dev Returns if transfers are enabled\n     */\n    function transfersEnabled() public view returns (bool) {\n        return _transfersEnabled;\n    }\n    \n    /**\n     * @dev Returns the minter address\n     */\n    function minter() public view returns (address) {\n        return _minter;\n    }\n    \n    /**\n     * @dev Returns the maximum supply\n     */\n    function maxSupply() public view returns (uint256) {\n        return _maxSupply;\n    }\n    \n    // ========== Transfer Functions ==========\n    \n    /**\n     * @dev NEP-17 transfer function\n     */\n    function transfer(\n        address from,\n        address to,\n        uint256 amount,\n        Any calldata data\n    ) public override whenTransfersEnabled validReceiver(to) validAmount(amount) returns (bool) {\n        // Check authorization\n        require(\n            from == msg.sender || \n            _allowances[from][msg.sender] >= amount ||\n            Runtime.checkWitness(from),\n            \"NEP17: unauthorized transfer\"\n        );\n        \n        _transfer(from, to, amount, data);\n        \n        // Update allowance if needed\n        if (from != msg.sender && _allowances[from][msg.sender] != type(uint256).max) {\n            _approve(from, msg.sender, _allowances[from][msg.sender] - amount);\n        }\n        \n        return true;\n    }\n    \n    /**\n     * @dev Standard ERC-20 transfer\n     */\n    function transfer(address to, uint256 amount) public returns (bool) {\n        return transfer(msg.sender, to, amount, \"\");\n    }\n    \n    /**\n     * @dev Transfer from (ERC-20 compatibility)\n     */\n    function transferFrom(address from, address to, uint256 amount) public returns (bool) {\n        return transfer(from, to, amount, \"\");\n    }\n    \n    /**\n     * @dev Approve spender\n     */\n    function approve(address spender, uint256 amount) public returns (bool) {\n        _approve(msg.sender, spender, amount);\n        return true;\n    }\n    \n    /**\n     * @dev Increase allowance\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {\n        _approve(msg.sender, spender, _allowances[msg.sender][spender] + addedValue);\n        return true;\n    }\n    \n    /**\n     * @dev Decrease allowance\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {\n        uint256 currentAllowance = _allowances[msg.sender][spender];\n        require(currentAllowance >= subtractedValue, \"NEP17: decreased allowance below zero\");\n        _approve(msg.sender, spender, currentAllowance - subtractedValue);\n        return true;\n    }\n    \n    // ========== Minting and Burning ==========\n    \n    /**\n     * @dev Mint tokens\n     */\n    function mint(address to, uint256 amount) public onlyMinter validReceiver(to) validAmount(amount) {\n        if (_maxSupply > 0 && _totalSupply + amount > _maxSupply) {\n            revert NEP17ExceedsMaxSupply(amount, _maxSupply);\n        }\n        \n        _mint(to, amount);\n    }\n    \n    /**\n     * @dev Burn tokens\n     */\n    function burn(uint256 amount) public validAmount(amount) {\n        _burn(msg.sender, amount);\n    }\n    \n    /**\n     * @dev Burn tokens from account (with allowance)\n     */\n    function burnFrom(address from, uint256 amount) public validAmount(amount) {\n        uint256 currentAllowance = _allowances[from][msg.sender];\n        require(currentAllowance >= amount, \"NEP17: burn amount exceeds allowance\");\n        \n        _burn(from, amount);\n        _approve(from, msg.sender, currentAllowance - amount);\n    }\n    \n    // ========== Admin Functions ==========\n    \n    /**\n     * @dev Enable transfers\n     */\n    function enableTransfers() public onlyOwner {\n        require(!_transfersEnabled, \"NEP17: transfers already enabled\");\n        _transfersEnabled = true;\n        emit TransfersEnabled();\n    }\n    \n    /**\n     * @dev Disable transfers\n     */\n    function disableTransfers() public onlyOwner {\n        require(_transfersEnabled, \"NEP17: transfers already disabled\");\n        _transfersEnabled = false;\n        emit TransfersDisabled();\n    }\n    \n    /**\n     * @dev Change minter\n     */\n    function changeMinter(address newMinter) public onlyOwner {\n        require(newMinter != address(0), \"NEP17: new minter is zero address\");\n        address oldMinter = _minter;\n        _minter = newMinter;\n        emit MinterChanged(oldMinter, newMinter);\n    }\n    \n    /**\n     * @dev Set maximum supply\n     */\n    function setMaxSupply(uint256 newMaxSupply) public onlyOwner {\n        require(newMaxSupply >= _totalSupply, \"NEP17: max supply below current supply\");\n        _maxSupply = newMaxSupply;\n        emit MaxSupplySet(newMaxSupply);\n    }\n    \n    // ========== Batch Operations ==========\n    \n    /**\n     * @dev Batch transfer to multiple recipients\n     */\n    function batchTransfer(\n        address[] memory recipients,\n        uint256[] memory amounts,\n        bytes[] memory data\n    ) public whenTransfersEnabled returns (bool) {\n        require(recipients.length == amounts.length, \"NEP17: array length mismatch\");\n        require(recipients.length == data.length, \"NEP17: array length mismatch\");\n        require(recipients.length > 0, \"NEP17: empty arrays\");\n        require(recipients.length <= 100, \"NEP17: too many recipients\");\n        \n        for (uint256 i = 0; i < recipients.length; i++) {\n            transfer(msg.sender, recipients[i], amounts[i], data[i]);\n        }\n        \n        return true;\n    }\n    \n    /**\n     * @dev Batch mint to multiple recipients\n     */\n    function batchMint(address[] memory recipients, uint256[] memory amounts) \n        public \n        onlyMinter \n        returns (bool) \n    {\n        require(recipients.length == amounts.length, \"NEP17: array length mismatch\");\n        require(recipients.length > 0, \"NEP17: empty arrays\");\n        require(recipients.length <= 100, \"NEP17: too many recipients\");\n        \n        for (uint256 i = 0; i < recipients.length; i++) {\n            mint(recipients[i], amounts[i]);\n        }\n        \n        return true;\n    }\n    \n    // ========== Internal Functions ==========\n    \n    /**\n     * @dev Internal transfer function\n     */\n    function _transfer(address from, address to, uint256 amount, Any memory data) internal {\n        uint256 fromBalance = _balances[from];\n        if (fromBalance < amount) {\n            revert NEP17InsufficientBalance(from, fromBalance, amount);\n        }\n        \n        unchecked {\n            _balances[from] = fromBalance - amount;\n        }\n        _balances[to] += amount;\n        \n        emit Transfer(from, to, amount);\n        \n        // Call onNEP17Payment if recipient is a contract\n        if (to.code.length > 0) {\n            try INEP17Receiver(to).onNEP17Payment(from, amount, data) {\n                // Success\n            } catch {\n                // Revert if recipient doesn't implement interface correctly\n                revert NEP17InvalidReceiver(to);\n            }\n        }\n    }\n    \n    /**\n     * @dev Internal mint function\n     */\n    function _mint(address to, uint256 amount) internal {\n        _totalSupply += amount;\n        _balances[to] += amount;\n        \n        emit Transfer(address(0), to, amount);\n        emit Mint(to, amount);\n        \n        // Call onNEP17Payment if recipient is a contract\n        if (to.code.length > 0) {\n            try INEP17Receiver(to).onNEP17Payment(address(0), amount, \"\") {\n                // Success\n            } catch {\n                // Mint can proceed even if recipient doesn't implement interface\n            }\n        }\n    }\n    \n    /**\n     * @dev Internal burn function\n     */\n    function _burn(address from, uint256 amount) internal {\n        uint256 accountBalance = _balances[from];\n        if (accountBalance < amount) {\n            revert NEP17InsufficientBalance(from, accountBalance, amount);\n        }\n        \n        unchecked {\n            _balances[from] = accountBalance - amount;\n        }\n        // Keep totalSupply decrement checked for defense-in-depth\n        _totalSupply -= amount;\n\n        emit Transfer(from, address(0), amount);\n        emit Burn(from, amount);\n    }\n    \n    /**\n     * @dev Internal approve function\n     */\n    function _approve(address owner, address spender, uint256 amount) internal {\n        require(owner != address(0), \"NEP17: approve from zero address\");\n        require(spender != address(0), \"NEP17: approve to zero address\");\n        \n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n    \n    // ========== Neo Integration Functions ==========\n    \n    /**\n     * @dev Get token holders count (expensive operation)\n     */\n    function getHoldersCount() public view returns (uint256) {\n        // Use storage iterator to count all balance entries\n        Storage.Iterator memory iterator = Storage.find(abi.encode(\"balance\"));\n        uint256 count = 0;\n        \n        while (iterator.next() && count < 10000) { // Limit to prevent gas exhaustion\n            bytes memory balance = iterator.value();\n            if (balance.length > 0) {\n                uint256 amount = abi.decode(balance, (uint256));\n                if (amount > 0) {\n                    count++;\n                }\n            }\n        }\n        \n        return count;\n    }\n    \n    /**\n     * @dev Get token info for Neo blockchain\n     */\n    function getTokenInfo() public view virtual returns (\n        string memory tokenName,\n        string memory tokenSymbol,\n        uint8 tokenDecimals,\n        uint256 tokenTotalSupply,\n        uint256 tokenMaxSupply,\n        address tokenMinter,\n        bool tokenTransfersEnabled\n    ) {\n        return (_name, _symbol, _decimals, _totalSupply, _maxSupply, _minter, _transfersEnabled);\n    }\n    \n    /**\n     * @dev Get contract metadata for Neo\n     */\n    function getContractMetadata() public view virtual returns (\n        string memory standard,\n        string memory name,\n        string memory version,\n        string memory author\n    ) {\n        return (\n            \"NEP-17\",\n            \"Neo N3 Fungible Token\",\n            \"1.0.0\",\n            \"Jimmy <jimmy@r3e.network>\"\n        );\n    }\n    \n    // ========== Emergency Functions ==========\n    \n    /**\n     * @dev Emergency pause (disable transfers)\n     */\n    function emergencyPause() public virtual onlyOwner {\n        disableTransfers();\n        emit EmergencyPause(msg.sender, block.timestamp);\n    }\n    \n    /**\n     * @dev Emergency unpause (enable transfers)\n     */\n    function emergencyUnpause() public onlyOwner {\n        enableTransfers();\n        emit EmergencyUnpause(msg.sender, block.timestamp);\n    }\n    \n    // ========== Advanced Features ==========\n    \n    /**\n     * @dev Time-locked transfer\n     */\n    function transferWithTimelock(\n        address to,\n        uint256 amount,\n        uint256 releaseTime\n    ) public whenTransfersEnabled validReceiver(to) validAmount(amount) {\n        require(releaseTime > block.timestamp, \"NEP17: release time must be in future\");\n        \n        // Store the time-locked transfer\n        bytes32 timelockId = keccak256(abi.encode(msg.sender, to, amount, releaseTime, block.timestamp));\n        \n        // Transfer to this contract temporarily\n        _transfer(msg.sender, address(this), amount, \"\");\n        \n        // Store timelock info\n        Storage.put(\n            abi.encode(\"timelock\", timelockId),\n            abi.encode(msg.sender, to, amount, releaseTime)\n        );\n        \n        // Emit event\n        emit TimelockCreated(timelockId, msg.sender, to, amount, releaseTime);\n    }\n    \n    /**\n     * @dev Claim time-locked tokens\n     */\n    function claimTimelock(bytes32 timelockId) public {\n        bytes memory timelockData = Storage.get(abi.encode(\"timelock\", timelockId));\n        require(timelockData.length > 0, \"NEP17: timelock not found\");\n        \n        (address from, address to, uint256 amount, uint256 releaseTime) = \n            abi.decode(timelockData, (address, address, uint256, uint256));\n        \n        require(block.timestamp >= releaseTime, \"NEP17: timelock not yet expired\");\n        require(msg.sender == to, \"NEP17: only recipient can claim\");\n        \n        // Delete timelock\n        Storage.remove(abi.encode(\"timelock\", timelockId));\n        \n        // Transfer tokens\n        _transfer(address(this), to, amount, \"\");\n        \n        // Emit event\n        emit TimelockClaimed(timelockId, to, amount);\n    }\n    \n    /**\n     * @dev Multi-signature transfer\n     */\n    function multiSigTransfer(\n        address to,\n        uint256 amount,\n        address[] memory signers,\n        bytes[] memory signatures\n    ) public whenTransfersEnabled validReceiver(to) validAmount(amount) {\n        require(signers.length == signatures.length, \"NEP17: array length mismatch\");\n        require(signers.length >= 2, \"NEP17: minimum 2 signers required\");\n        require(signers.length <= 10, \"NEP17: maximum 10 signers allowed\");\n\n        // Off-chain signatures are collected by clients, but on-chain authorization\n        // is enforced via Neo witness checks for each declared signer.\n        signatures;\n\n        for (uint256 i = 0; i < signers.length; i++) {\n            address signer = signers[i];\n            require(signer != address(0), \"NEP17: invalid signer\");\n\n            // Prevent duplicate signers from satisfying quorum multiple times.\n            for (uint256 j = 0; j < i; j++) {\n                require(signers[j] != signer, \"NEP17: duplicate signer\");\n            }\n\n            require(Runtime.checkWitness(signer), \"NEP17: signer witness missing\");\n        }\n        \n        // Execute transfer from multisig pool\n        _transfer(address(this), to, amount, abi.encode(\"multisig\", signers));\n    }\n    \n    /**\n     * @dev Conditional transfer based on oracle data\n     */\n    function conditionalTransfer(\n        address to,\n        uint256 amount,\n        string memory oracleUrl,\n        string memory condition\n    ) public whenTransfersEnabled validReceiver(to) validAmount(amount) {\n        // Escrow tokens in contract until condition is met\n        _transfer(msg.sender, address(this), amount, \"\");\n        \n        // Create request id and escrow record.\n        // Include a monotonic nonce to avoid collisions for repeated same-params requests.\n        uint256 nonce = _conditionalTransferNonce++;\n        bytes32 requestId = keccak256(abi.encode(msg.sender, to, amount, condition, block.timestamp, nonce));\n\n        // Store pending transfer by local request id so callbacks can be validated and replay-protected.\n        Storage.put(\n            abi.encode(\"conditional_transfer\", requestId),\n            abi.encode(msg.sender, to, amount)\n        );\n\n        // Pass only the local request id through oracle userData; callback must load escrowed state.\n        Syscalls.oracleRequest(\n            oracleUrl,\n            condition,\n            \"conditionalTransferCallback\",\n            abi.encode(requestId),\n            10000000\n        );\n\n        emit ConditionalTransferCreated(requestId, msg.sender, to, amount);\n    }\n    \n    /**\n     * @dev Oracle callback for conditional transfers\n     */\n    function conditionalTransferCallback(\n        uint256 requestId,\n        uint256 code,\n        bytes calldata result,\n        bytes calldata userData\n    ) external {\n        requestId; // Oracle-native request id (reserved for diagnostics)\n        require(msg.sender == ORACLE_NATIVE_CONTRACT, \"NEP17: unauthorized callback\");\n\n        bytes32 localRequestId = abi.decode(userData, (bytes32));\n        bytes memory pending = Storage.get(abi.encode(\"conditional_transfer\", localRequestId));\n        require(pending.length > 0, \"NEP17: conditional transfer not found\");\n\n        (address from, address to, uint256 amount) = abi.decode(pending, (address, address, uint256));\n\n        // Consume request before state transitions to prevent callback replay.\n        Storage.remove(abi.encode(\"conditional_transfer\", localRequestId));\n\n        if (code == 0 && abi.decode(result, (bool))) {\n            _transfer(address(this), to, amount, \"\");\n            emit ConditionalTransferExecuted(from, to, amount);\n        } else {\n            // Refund escrowed tokens on oracle errors or unmet conditions.\n            _transfer(address(this), from, amount, \"\");\n            emit ConditionalTransferFailed(from, amount);\n        }\n    }\n    \n    /**\n     * @dev Get all balances (expensive operation, use carefully)\n     */\n    function getAllBalances() public view returns (address[] memory accounts, uint256[] memory balances) {\n        // Use storage iterator to get all balance entries\n        Storage.Iterator memory iterator = Storage.find(abi.encode(\"balance\"));\n        \n        // Temporary arrays with maximum size\n        address[] memory tempAccounts = new address[](1000);\n        uint256[] memory tempBalances = new uint256[](1000);\n        uint256 count = 0;\n        \n        while (iterator.next() && count < 1000) {\n            bytes memory balanceData = iterator.value();\n            if (balanceData.length > 0) {\n                uint256 balance = abi.decode(balanceData, (uint256));\n                if (balance > 0) {\n                    // Extract address from key\n                    bytes memory key = iterator.currentKey;\n                    address account = abi.decode(key, (address));\n                    \n                    tempAccounts[count] = account;\n                    tempBalances[count] = balance;\n                    count++;\n                }\n            }\n        }\n        \n        // Resize arrays to actual count\n        accounts = new address[](count);\n        balances = new uint256[](count);\n        \n        for (uint256 i = 0; i < count; i++) {\n            accounts[i] = tempAccounts[i];\n            balances[i] = tempBalances[i];\n        }\n    }\n    \n    /**\n     * @dev NEP-17 specific metadata\n     */\n    function nep17Metadata() public view returns (\n        string memory standard,\n        bytes memory logo,\n        string memory website,\n        string memory description\n    ) {\n        return (\n            \"NEP-17\",\n            \"\", // Logo data (optional)\n            \"https://r3e.network\",\n            string(abi.encodePacked(\"NEP-17 token: \", _name))\n        );\n    }\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    }
  }
}