# Solidity Development Guidelines for Asset Tokenization Kit

## General Principles

- **Think first, code second**: Minimize the number of lines changed and consider ripple effects across the codebase.
- **Prefer simplicity**: Fewer moving parts → fewer bugs and lower audit overhead.

## Assembly Usage

| Rule | Rationale |
|------|-----------|
| Use assembly only when essential. | Keeps code readable and auditable. |
| Assembly is mandatory for low-level external calls. | Gives full control over call parameters & return data, and saves gas. |
| Precede every assembly block with: • A brief justification (1-2 lines). • Equivalent Solidity pseudocode. | Documents intent for reviewers. |
| Mark assembly blocks memory-safe when the Solidity docs' criteria are met. | Enables compiler optimizations. |

## Gas Optimization

- Keep a dedicated **Gas Optimization** section in the PR description; justify any measurable gas deltas.
- Prefer `calldata` over `memory`.
- Limit storage (`sstore`, `sload`) operations; cache in memory wherever possible.
- Use forge snapshot and benchmarks:
  ```bash
  forge snapshot                # Create gas snapshot
  forge test --gas-report       # Gas report for tests
  forge test --match-test bench # Run benchmarks
  ```
- Large regressions must be explained.

## Handling "Stack Too Deep"

- **Struct hack (tests only)**: Bundle local variables into a temporary struct declared above the test.
- **Scoped blocks**: Wrap code in `{ ... }` to drop unused vars from the stack.
- **Internal helper functions**: Encapsulate logic to shorten call frames.
- **Refactor / delete unnecessary variables before other tricks**.

## Security Checklist

- Review every change with an adversarial mindset.
- Favor the simplest design that meets requirements.
- After coding, ask: "What new attack surface did I introduce?"
- Reject any change that raises security risk without strong justification.
- Follow SMART protocol security patterns for ERC-3643 compliance.

## Error Handling Style

Always use custom errors with the revert pattern instead of require statements:

```solidity
// ❌ Don't use require with string messages
require(amount > 0, "Amount must be positive");
require(to != address(0), "Cannot transfer to zero address");

// ✅ Do use custom errors with if/revert pattern
error AmountMustBePositive();
error CannotTransferToZeroAddress();

if (amount == 0) revert AmountMustBePositive();
if (to == address(0)) revert CannotTransferToZeroAddress();
```

**Benefits of custom errors**:
- More gas efficient than require strings
- Better error identification in tests and debugging
- Cleaner, more professional code
- Consistent with modern Solidity best practices

## Testing Guidelines

### Core Testing Principles

**Every feature or change MUST have comprehensive tests before creating a PR**. This is non-negotiable for maintaining code quality and preventing regressions.

### When to Write Tests

- **New Features**: Write tests that demonstrate the complete flow and all edge cases
- **Bug Fixes**: Add tests that reproduce the bug and verify the fix
- **Refactoring**: Ensure existing tests still pass; add new ones if behavior changes
- **Gas Optimizations**: Include benchmark tests showing before/after comparisons

### Types of Required Tests

**Unit Tests**:
- Write clear unit tests that demonstrate the general flow of your feature/change
- Test both happy paths and failure cases
- Include edge cases and boundary conditions
- Test revert conditions with specific error messages

**Fuzz Tests**:
- **Fuzz tests are highly encouraged** for all new functionality
- Use Foundry's built-in fuzzing capabilities
- Apply random arguments to thoroughly test your implementation

Example fuzz test pattern:
```solidity
function testFuzz_myFeature(uint256 amount, address user) public {
    // Bound inputs to reasonable ranges
    amount = bound(amount, 1, type(uint128).max);
    vm.assume(user != address(0));
    
    // Test your feature with random inputs
    myContract.myFeature(amount, user);
    
    // Assert expected outcomes
    assertEq(myContract.balanceOf(user), amount);
}
```

### Testing Checklist Before PR

Before opening any PR, ensure:
- [ ] All new functions have unit tests
- [ ] Critical paths have fuzz tests with random inputs
- [ ] Edge cases and revert scenarios are tested
- [ ] Gas benchmarks are included for optimizations
- [ ] All tests pass: `forge test`
- [ ] No test coverage regression: `forge coverage`

## Verification Workflow

```bash
forge build                    # compile
forge test                     # full test suite
forge snapshot                 # gas snapshot
forge test --match-test bench  # run benchmarks
forge test --gas-report        # gas usage report
forge coverage                 # code coverage
```

## Asset Tokenization Kit Specific Guidelines

### Contract Structure
- Follow the SMART protocol patterns for all asset implementations
- Use the established factory pattern (`ATKBondFactory`, `ATKEquityFactory`, etc.)
- Implement proper ERC-3643 compliance for all tokenized assets
- Utilize the extension system (`SMARTBurnable`, `SMARTCapped`, etc.) for modularity

### Testing Assets
When testing tokenized assets:
- Test compliance features (identity registry, claim topics)
- Test factory deployment patterns
- Test proxy upgradeability
- Test all extensions used by the asset
- Include integration tests with the compliance system

### Common Patterns
- Use `AccessControl` for role-based permissions
- Implement `Pausable` for emergency stops
- Follow ERC-3643 for identity and compliance
- Use proxy patterns for upgradeability

### Available Tools

The Asset Tokenization Kit includes:
- Foundry for contract compilation and testing
- OpenZeppelin contracts for base implementations
- SMART protocol contracts for compliance
- Hardhat for additional tooling support

### Project Structure

- `contracts/`: Smart contract source files
  - `assets/`: Asset factories and implementations
  - `smart/`: SMART protocol base contracts and extensions
  - `system/`: Compliance and registry contracts
  - `test/`: Test contracts and utilities
- `test/`: Foundry tests
- `scripts/`: Deployment and utility scripts

## Critical Reminders

### DO NOT

- Use require() statements - always use custom errors
- Create contracts without comprehensive tests
- Make gas-intensive changes without benchmarks
- Skip security considerations for any change
- Use inline strings for errors

### ALWAYS

- Follow SMART protocol patterns
- Test all compliance features
- Measure gas impact of changes
- Consider upgradeability implications
- Use established factory patterns
- Document assembly blocks
- Run full test suite before PR

## Continuous Learning

- Consult SMART protocol documentation
- Review OpenZeppelin best practices
- Study ERC-3643 compliance requirements
- Learn from audited tokenization projects

Apply these rules rigorously when working with Solidity files in the Asset Tokenization Kit.