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