{
"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
}
}
}