{"filename":"xian-smart-contracts-cursor-rules-prompt-file.mdc","content":"---\ndescription: \"Cursor rules for Xian Smart Contracts.\"\nglobs: **/*\nalwaysApply: false\n---\n# Xian Smart Contract Development - Cursor Rules\n\nXIAN is the currency of the Xian blockchain.\nNever mention TAU or Lamden.\n\n## Contract Structure\n\n### Basic Structure\n- Smart contracts are written in native Python without transpilation\n- Contract names must follow the pattern: `^con_[a-z][a-z0-9_]*$`\n- Contract names must start with 'con_' prefix (except system contracts like 'currency')\n- Contract names must be lowercase, only contain letters, numbers and underscores after prefix\n- Contract names must be max 64 characters\n\n### Naming Conventions\n- You cannot use '_' as a prefix for variables or functions (e.g., `_private_var` is not allowed)\n- Follow standard Python naming conventions otherwise\n- Use descriptive names for clarity\n- A contract can not be deployed by another contract\n\n### Function Types\n- `@export` decorator defines public functions callable by any user or contract\n- `@construct` decorator defines initialization function executed once at contract submission (optional)\n- Functions without decorators are private and can only be called by the contract itself\n- Functions with `@export` can call private functions internally\n\n### Constructor Arguments\n- Optional arguments can be provided to the `@construct` function\n- Initial state can be setup using these arguments\n\n## State Management\n\n### Variable\n- `Variable` is a way to define a singular state variable in the contract\n- Use `variable.set(value)` to modify\n- Use `variable.get()` to retrieve\n\n```python\nmy_var = Variable()\n\n@construct\ndef seed():\n    my_var.set(0)  # Initialize variable\n\n@export\ndef increment():\n    my_var.set(my_var.get() + 1)\n```\n\n### Hash\n- `Hash` is a key-value store for the contract\n- Default value can be specified with `Hash(default_value=0)`\n- Access through dictionary-like syntax: `hash[key] = value` and `hash[key]`\n- Supports nested keys with tuple: `hash[key1, key2] = value`\n\n```python\nmy_hash = Hash(default_value=0)\n\n@export\ndef set_value(key: str, value: int):\n    my_hash[key] = value\n\n@export\ndef get_value(key: str):\n    return my_hash[key]\n```\n\n#### Illegal Delimiters \n\":\" and \".\" cannot be used in Variable or Hash keys.\n\n### Foreign State Access\n- `ForeignHash` provides read-only access to a Hash from another contract\n- `ForeignVariable` provides read-only access to a Variable from another contract\n\n```python\ntoken_balances = ForeignHash(foreign_contract='con_my_token', foreign_name='balances')\nfoundation_owner = ForeignVariable(foreign_contract='foundation', foreign_name='owner')\n```\n\n## Context Variables\n\n### ctx.caller\n- The identity of the person or contract calling the function\n- Changes when a contract calls another contract's function\n- Used for permission checks in token contracts\n\n### ctx.signer\n- The top-level user who signed the transaction\n- Remains constant throughout transaction execution\n- Only used for security guards/blacklisting, not for account authorization\n\n### ctx.this\n- The identity/name of the current contract\n- Never changes\n- Useful when the contract needs to refer to itself\n\n### ctx.owner\n- Owner of the contract, optional field set at time of submission\n- Only the owner can call exported functions if set\n- Can be changed with `ctx.owner = new_owner`\n\n### ctx.entry\n- Returns tuple of (contract_name, function_name) of the original entry point\n- Helps identify what contract and function initiated the call chain\n\n## Built-in Variables\n\n### Time and Blockchain Information\n- `now` - Returns the current datetime\n- `block_num` - Returns the current block number, useful for block-dependent logic\n- `block_hash` - Returns the current block hash, can be used as a source of randomness\n\nExample usage:\n```python\n@construct\ndef seed():\n    submission_time = Variable()\n    submission_block_num = Variable()\n    submission_block_hash = Variable()\n    \n    # Store blockchain state at contract creation\n    submission_time.set(now)\n    submission_block_num.set(block_num)\n    submission_block_hash.set(block_hash)\n```\n\n## Imports and Contract Interaction\n\n### Importing Contracts\n- Use `importlib.import_module(contract_name)` for dynamic contract imports\n- Static contract imports can be done with `import <contract_name>`\n- Only use 'import' syntax for contracts, not for libraries or Python modules\n- Trying to import standard libraries will not work within a contract (they're automatically available)\n- Dynamic imports are preferred when the contract name is determined at runtime\n- Can enforce interface with `importlib.enforce_interface()`\n- NEVER import anything other than a contract.\n- ALL contracting libraries are available globally\n- NEVER IMPORT importlib. It is already available globally.\n\n```python\n@export\ndef interact_with_token(token_contract: str, recipient: str, amount: float):\n    token = importlib.import_module(token_contract)\n    \n    # Define expected interface\n    interface = [\n        importlib.Func('transfer', args=('amount', 'to')),\n        importlib.Var('balances', Hash)\n    ]\n    \n    # Enforce interface\n    assert importlib.enforce_interface(token, interface)\n    \n    # Call function on other contract\n    token.transfer(amount=amount, to=recipient)\n```\n\n## Error Handling\n\n### Assertions\n- Use `assert` statements for validation and error checking\n- Include error messages: `assert condition, \"Error message\"`\n\n### No Try/Except\n- Exception handling with try/except is not allowed\n- Use conditional logic with if/else statements instead\n\n```python\n# DO NOT USE:\ntry:\n    result = 100 / value\nexcept:\n    result = 0\n\n# CORRECT APPROACH:\nassert value != 0, \"Cannot divide by zero\"\nresult = 100 / value\n\n# OR\nif value == 0:\n    result = 0\nelse:\n    result = 100 / value\n```\n\n### Prohibited Built-ins\n- `getattr` is an illegal built-in function and must not be used\n- Other Python built-ins may also be restricted for security reasons\n\n## Modules\n\n### Random\n- Seed RNG with `random.seed()`\n- Generate random integers with `random.randint(min, max)`\n\n### Datetime\n- Available by default without importing\n- Compare timestamps with standard comparison operators\n- Use the built-in `now` variable for current time\n\n### Crypto\n- Provides cryptographic functionality using the PyNaCl library under the hood\n- Employs the Ed25519 signature scheme for digital signatures\n- Main function is `verify` for signature validation\n\n```python\n# Verify a signature\nis_valid = crypto.verify(vk, msg, signature)\n# Returns True if the signature is valid for the given message and verification key\n```\n\nExample usage in a contract:\n```python\n@export\ndef verify_signature(vk: str, msg: str, signature: str):\n    # Use the verify function to check if the signature is valid \n    is_valid = crypto.verify(vk, msg, signature)\n    \n    # Return the result of the verification\n    return is_valid\n```\n\n### Hashlib\n- Xian provides a simplified version of hashlib with a different API than Python's standard library\n- Does not require setting up an object and updating it with bytes\n- Functions directly accept and return hexadecimal strings\n\n```python\n# Hash a hex string with SHA3 (256 bit)\nhash_result = hashlib.sha3(\"68656c6c6f20776f726c64\")  # hex for \"hello world\"\n\n# If not a valid hex string, it will encode the string to bytes first\ntext_hash = hashlib.sha3(\"hello world\")\n\n# SHA256 works the same way (SHA2 256-bit, used in Bitcoin)\nsha256_result = hashlib.sha256(\"68656c6c6f20776f726c64\")\n```\n\n## Testing\n\n### Setting Up Tests\n- Use Python's unittest framework\n- Client available via `from contracting.client import ContractingClient`\n- Flush client before and after each test\n\n### Setting Test Environment\n- Pass environment variables like `now` (datetime) in a dictionary\n\n```python\nfrom contracting.stdlib.bridge.time import Datetime\n\nenv = {\"now\": Datetime(year=2021, month=1, day=1, hour=0)}\nresult = self.some_contract.some_fn(some_arg=some_value, environment=env)\n```\n\n### Specifying Signer\n- Specify the signer when calling contract functions in tests\n\n```python\nresult = self.some_contract.some_fn(some_arg=some_value, signer=\"some_signer\")\n```\n\n## Events\n\n### Defining Events\n- Use `LogEvent` to define events at the top level of a contract\n- Each event has a name and a schema of parameters with their types\n- Set `idx: True` for parameters that should be indexed for querying\n\n```python\nTransferEvent = LogEvent(\n    event=\"Transfer\",\n    params={\n        \"from\": {'type': str, 'idx': True},\n        \"to\": {'type': str, 'idx': True},\n        \"amount\": {'type': (int, float, decimal)}\n    }\n)\n\nApprovalEvent = LogEvent(\n    event=\"Approval\",\n    params={\n        \"owner\": {'type': str, 'idx': True},\n        \"spender\": {'type': str, 'idx': True},\n        \"amount\": {'type': (int, float, decimal)}\n    }\n)\n```\n\n### Emitting Events\n- Call the event variable as a function and pass a dictionary of parameter values\n- All parameters defined in the event schema must be provided\n- Event parameters must match the specified types\n\n```python\n@export\ndef transfer(amount: float, to: str):\n    sender = ctx.caller\n    \n    # ... perform transfer logic ...\n    \n    # Emit the transfer event\n    TransferEvent({\n        \"from\": sender,\n        \"to\": to,\n        \"amount\": amount\n    })\n```\n\n### Testing Events\n- Use `return_full_output=True` when calling contract functions in tests to capture events\n- Access events in the result dictionary's 'events' key\n- Assert on event types and parameters in tests\n\n```python\n# In your test function\nresult = self.contract.transfer(\n    amount=100,\n    to=\"recipient\",\n    signer=\"sender\",\n    return_full_output=True\n)\n\n# Verify events\nevents = result['events']\nassert len(events) == 1\nassert events[0]['event'] == 'Transfer'\nassert events[0]['from'] == 'sender'\nassert events[0]['to'] == 'recipient'\nassert events[0]['amount'] == 100\n```\n\n### Common Event Types\n- Transfer: When value moves between accounts\n- Approval: When spending permissions are granted\n- Mint/Burn: When tokens are created or destroyed\n- StateChange: When significant contract state changes\n- ActionPerformed: When important contract actions execute\n\n## Smart Contract Testing Best Practices\n\n### Test Structure\n- Use Python's unittest framework for structured testing\n- Create a proper test class that inherits from `unittest.TestCase`\n- Implement `setUp` and `tearDown` methods to isolate tests\n- Define the environment and chain ID in setUp for consistent testing\n\n```python\nclass TestMyContract(unittest.TestCase):\n    def setUp(self):\n        # Bootstrap the environment\n        self.chain_id = \"test-chain\"\n        self.environment = {\"chain_id\": self.chain_id}\n        self.deployer_vk = \"test-deployer\"\n        \n        # Initialize the client\n        self.client = ContractingClient(environment=self.environment)\n        self.client.flush()\n        \n        # Load and submit the contract\n        with open('path/to/my_contract.py') as f:\n            code = f.read()\n            self.client.submit(code, name=\"my_contract\", constructor_args={\"owner\": self.deployer_vk})\n            \n        # Get contract instance\n        self.contract = self.client.get_contract(\"my_contract\")\n        \n    def tearDown(self):\n        # Clean up after each test\n        self.client.flush()\n```\n\n### Test Organization\n- Group tests by functionality using descriptive method names\n- Follow the Given-When-Then pattern for clear test cases\n- Test both positive paths and error cases\n- Define all variables within the test, not in setUp\n- Define all variables and parameters used by a test WITHIN THE TEST, not within setUp\n- This ensures test isolation and prevents unexpected side effects between tests\n\n```python\ndef test_transfer_success(self):\n    # GIVEN a sender with balance\n    sender = \"alice\"\n    self.contract.balances[sender] = 1000\n    \n    # WHEN a transfer is executed\n    result = self.contract.transfer(amount=100, to=\"bob\", signer=sender)\n    \n    # THEN the balances should be updated correctly\n    self.assertEqual(self.contract.balances[\"bob\"], 100)\n    self.assertEqual(self.contract.balances[sender], 900)\n```\n\n### Testing for Security Vulnerabilities\n\n#### 1. Authorization and Access Control\n- Test that only authorized users can perform restricted actions\n- Verify that contract functions check `ctx.caller` or `ctx.signer` appropriately\n\n```python\ndef test_change_metadata_unauthorized(self):\n    # GIVEN a non-operator trying to change metadata\n    with self.assertRaises(Exception):\n        self.contract.change_metadata(key=\"name\", value=\"NEW\", signer=\"attacker\")\n```\n\n#### 2. Replay Attack Protection\n- Test that transaction signatures cannot be reused\n- Verify nonce mechanisms or one-time-use permits\n\n```python\ndef test_permit_double_spending(self):\n    # GIVEN a permit already used once\n    self.contract.permit(owner=\"alice\", spender=\"bob\", value=100, deadline=deadline, \n                        signature=signature)\n    \n    # WHEN the permit is used again\n    # THEN it should fail\n    with self.assertRaises(Exception):\n        self.contract.permit(owner=\"alice\", spender=\"bob\", value=100, \n                            deadline=deadline, signature=signature)\n```\n\n#### 3. Time-Based Vulnerabilities\n- Test behavior around time boundaries (begin/end dates)\n- Test with different timestamps using the environment parameter\n\n```python\ndef test_time_sensitive_function(self):\n    # Test with time before deadline\n    env = {\"now\": Datetime(year=2023, month=1, day=1)}\n    result = self.contract.some_function(signer=\"alice\", environment=env)\n    self.assertTrue(result)\n    \n    # Test with time after deadline\n    env = {\"now\": Datetime(year=2024, month=1, day=1)}\n    with self.assertRaises(Exception):\n        self.contract.some_function(signer=\"alice\", environment=env)\n```\n\n#### 4. Balance and State Checks\n- Verify state changes after operations\n- Test for correct balance updates after transfers\n- Ensure state consistency through complex operations\n\n```python\ndef test_transfer_balances(self):\n    # Set initial balances\n    self.contract.balances[\"alice\"] = 1000\n    self.contract.balances[\"bob\"] = 500\n    \n    # Perform transfer\n    self.contract.transfer(amount=300, to=\"bob\", signer=\"alice\")\n    \n    # Verify final balances\n    self.assertEqual(self.contract.balances[\"alice\"], 700)\n    self.assertEqual(self.contract.balances[\"bob\"], 800)\n```\n\n#### 5. Signature Validation\n- Test with valid and invalid signatures\n- Test with modified parameters to ensure signatures aren't transferable\n\n```python\ndef test_signature_validation(self):\n    # GIVEN a properly signed message\n    signature = wallet.sign_msg(msg)\n    \n    # WHEN using the correct parameters\n    result = self.contract.verify_signature(msg=msg, signature=signature, \n                                          public_key=wallet.public_key)\n    \n    # THEN verification should succeed\n    self.assertTrue(result)\n    \n    # BUT when using modified parameters\n    with self.assertRaises(Exception):\n        self.contract.verify_signature(msg=msg+\"tampered\", signature=signature, \n                                     public_key=wallet.public_key)\n```\n\n#### 6. Edge Cases and Boundary Conditions\n- Test with zero values, max values, empty strings\n- Test operations at time boundaries (exactly at deadline)\n- Test with invalid inputs and malformed data\n\n```python\ndef test_edge_cases(self):\n    # Test with zero amount\n    with self.assertRaises(Exception):\n        self.contract.transfer(amount=0, to=\"receiver\", signer=\"sender\")\n    \n    # Test with negative amount\n    with self.assertRaises(Exception):\n        self.contract.transfer(amount=-100, to=\"receiver\", signer=\"sender\")\n```\n\n#### 7. Capturing and Verifying Events\n- Use `return_full_output=True` to capture events\n- Verify event emissions and their parameters\n\n```python\ndef test_event_emission(self):\n    # GIVEN a setup for transfer\n    sender = \"alice\"\n    receiver = \"bob\"\n    amount = 100\n    self.contract.balances[sender] = amount\n    \n    # WHEN executing with return_full_output\n    result = self.contract.transfer(\n        amount=amount, \n        to=receiver, \n        signer=sender,\n        return_full_output=True\n    )\n    \n    # THEN verify the event was emitted with correct parameters\n    self.assertIn('events', result)\n    events = result['events']\n    self.assertEqual(len(events), 1)\n    event = events[0]\n    self.assertEqual(event['event'], 'Transfer')\n    self.assertEqual(event['data_indexed']['from'], sender)\n    self.assertEqual(event['data_indexed']['to'], receiver)\n    self.assertEqual(event['data']['amount'], amount)\n```\n\n### Common Exploits to Test For\n\n#### Reentrancy\n- Test that state is updated before external calls\n- Verify operations complete atomically\n\n```python\ndef test_no_reentrancy_vulnerability(self):\n    # Set up the attack scenario (if possible with Xian)\n    \n    # Verify state is properly updated before any external calls\n    # For example, check that balances are decreased before tokens are sent\n    \n    # Verify proper operation ordering in the contract\n```\n\n#### Integer Overflow/Underflow\n- Test with extremely large numbers\n- Test arithmetic operations at boundaries\n\n```python\ndef test_integer_boundaries(self):\n    # Set a large balance\n    self.contract.balances[\"user\"] = 10**20\n    \n    # Test with large transfers\n    result = self.contract.transfer(amount=10**19, to=\"receiver\", signer=\"user\")\n    \n    # Verify results are as expected\n    self.assertEqual(self.contract.balances[\"user\"], 9*10**19)\n    self.assertEqual(self.contract.balances[\"receiver\"], 10**19)\n```\n\n#### Front-Running Protection\n- Test mechanisms that prevent frontrunning (e.g., commit-reveal)\n- Test deadline-based protections\n\n```python\ndef test_front_running_protection(self):\n    # Test with deadlines to ensure transactions expire\n    deadline = Datetime(year=2023, month=1, day=1)\n    current_time = Datetime(year=2023, month=1, day=2)  # After deadline\n    \n    with self.assertRaises(Exception):\n        self.contract.time_sensitive_operation(\n            param1=\"value\",\n            deadline=str(deadline),\n            environment={\"now\": current_time}\n        )\n```\n\n#### Authorization Bypass\n- Test authorization for all privileged operations\n- Try to access functions with different signers\n\n```python\ndef test_authorization_checks(self):\n    # Test admin functions with non-admin signers\n    with self.assertRaises(Exception):\n        self.contract.admin_function(param=\"value\", signer=\"regular_user\")\n    \n    # Test with proper authorization\n    result = self.contract.admin_function(param=\"value\", signer=\"admin\")\n    self.assertTrue(result)\n```\n\n### Best Practices Summary\n- Test both positive and negative paths\n- Test permissions and authorization thoroughly\n- Use environment variables to test time-dependent behavior\n- Verify event emissions using `return_full_output=True`\n- Test against potential replay attacks and signature validation\n- Check edge cases and boundary conditions\n- Verify state consistency after operations\n- Test for common security vulnerabilities\n"}