|
| 1 | +# Developer Guidelines |
| 2 | + |
| 3 | +This document provides comprehensive guidelines for developers contributing to the OADA UNHCR Yield Donation Module project. |
| 4 | + |
| 5 | +## 📋 Table of Contents |
| 6 | + |
| 7 | +- [Getting Started](#getting-started) |
| 8 | +- [Code Style](#code-style) |
| 9 | +- [Contract Development](#contract-development) |
| 10 | +- [Testing Guidelines](#testing-guidelines) |
| 11 | +- [Security Considerations](#security-considerations) |
| 12 | +- [Contributing](#contributing) |
| 13 | + |
| 14 | +## 🚀 Getting Started |
| 15 | + |
| 16 | +### Prerequisites |
| 17 | + |
| 18 | +- [Aiken](https://aiken-lang.org/) compiler (v1.9.0+) |
| 19 | +- [Nix](https://nixos.org/) package manager |
| 20 | +- Cardano development environment |
| 21 | + |
| 22 | +### Installation |
| 23 | + |
| 24 | +1. **Clone the repository**: |
| 25 | + |
| 26 | + ```bash |
| 27 | + git clone https://github.com/OptimFinance/clean-code.git |
| 28 | + cd yield-donation |
| 29 | + ``` |
| 30 | + |
| 31 | +2. **Setup development environment**: |
| 32 | + |
| 33 | + ```bash |
| 34 | + nix develop |
| 35 | + ``` |
| 36 | + |
| 37 | +3. **Install dependencies**: |
| 38 | + ```bash |
| 39 | + cd oada |
| 40 | + aiken check |
| 41 | + ``` |
| 42 | + |
| 43 | +### Project Structure |
| 44 | + |
| 45 | +``` |
| 46 | +oada-donate/ |
| 47 | +├── oada/ # Main Aiken project |
| 48 | +│ ├── validators/ # Smart contract validators |
| 49 | +│ ├── lib/ # Library modules |
| 50 | +│ ├── aiken.toml # Project configuration |
| 51 | +│ └── plutus.json # Plutus compatibility layer |
| 52 | +├── aiken-common/ # Shared Aiken utilities |
| 53 | +├── test/ # Test suite |
| 54 | +├── flake.nix # Nix development environment |
| 55 | +└── README.md # This file |
| 56 | +``` |
| 57 | + |
| 58 | +## 👨💻 Code Style |
| 59 | + |
| 60 | +### Naming Conventions |
| 61 | + |
| 62 | +- **Functions and Variables**: Use `snake_case` |
| 63 | +- **Types and Validators**: Use `PascalCase` |
| 64 | +- **Private Functions**: Prefix with underscore (`_`) |
| 65 | + |
| 66 | +### Documentation |
| 67 | + |
| 68 | +- Document all public functions with clear descriptions |
| 69 | +- Include parameter types and return values |
| 70 | +- Add examples for complex logic |
| 71 | +- Use inline comments for business logic explanations |
| 72 | + |
| 73 | +### Error Handling |
| 74 | + |
| 75 | +- Use `expect` for required values |
| 76 | +- Provide meaningful error messages |
| 77 | +- Handle edge cases explicitly |
| 78 | +- Validate inputs thoroughly |
| 79 | + |
| 80 | +## 🔧 Contract Development |
| 81 | + |
| 82 | +### Adding New Validators |
| 83 | + |
| 84 | +1. **Create the validator file** in `oada/validators/` |
| 85 | +2. **Define the datum type** with clear field descriptions |
| 86 | +3. **Implement required functions**: |
| 87 | + - `mint/2` for minting operations |
| 88 | + - `spend/3` for spending operations |
| 89 | +4. **Add comprehensive tests** |
| 90 | + |
| 91 | +#### Example Validator Structure |
| 92 | + |
| 93 | +```aiken |
| 94 | +validator(parameter1: Type1, parameter2: Type2) { |
| 95 | + fn mint(redeemer: RedeemerType, ctx: ScriptContext) { |
| 96 | + // Minting logic |
| 97 | + } |
| 98 | +
|
| 99 | + fn spend(datum: DatumType, redeemer: RedeemerType, ctx: ScriptContext) { |
| 100 | + // Spending logic |
| 101 | + } |
| 102 | +} |
| 103 | +``` |
| 104 | + |
| 105 | +### Validation Functions |
| 106 | + |
| 107 | +When creating validation functions in `lib/oada/validation.ak`: |
| 108 | + |
| 109 | +1. **Use clear parameter names** |
| 110 | +2. **Document the business logic** |
| 111 | +3. **Handle all edge cases** |
| 112 | +4. **Return boolean values for validation** |
| 113 | + |
| 114 | +### Datum and Redeemer Design |
| 115 | + |
| 116 | +#### Datum Guidelines |
| 117 | + |
| 118 | +- Keep datum structures minimal and focused |
| 119 | +- Use descriptive field names |
| 120 | +- Include validation constraints in the datum when possible |
| 121 | +- Document the purpose of each field |
| 122 | + |
| 123 | +#### Redeemer Guidelines |
| 124 | + |
| 125 | +- Design redeemers to be explicit about the action being performed |
| 126 | +- Use sum types for different operations |
| 127 | +- Include necessary parameters for validation |
| 128 | +- Keep redeemers immutable and stateless |
| 129 | + |
| 130 | +### Common Patterns |
| 131 | + |
| 132 | +#### Input Validation |
| 133 | + |
| 134 | +```aiken |
| 135 | +fn validate_input(input: Input, ctx: ScriptContext) -> Bool { |
| 136 | + and{ |
| 137 | + // Check input exists |
| 138 | + list.has(ctx.transaction.inputs, input)?, |
| 139 | + // Validate input value |
| 140 | + value.quantity_of(input.output.value, token_policy, "") > 0?, |
| 141 | + // Check authorization |
| 142 | + list.has(ctx.transaction.extra_signatories, required_key)? |
| 143 | + } |
| 144 | +} |
| 145 | +``` |
| 146 | + |
| 147 | +#### Output Validation |
| 148 | + |
| 149 | +```aiken |
| 150 | +fn validate_output(output: Output, expected_value: Int) -> Bool { |
| 151 | + and{ |
| 152 | + // Check output value |
| 153 | + value.quantity_of(output.value, token_policy, "") == expected_value?, |
| 154 | + // Validate address |
| 155 | + output.address.payment_credential == expected_credential?, |
| 156 | + // Check datum if required |
| 157 | + output.datum == expected_datum? |
| 158 | + } |
| 159 | +} |
| 160 | +``` |
| 161 | + |
| 162 | +## 🧪 Testing Guidelines |
| 163 | + |
| 164 | +### Test Types |
| 165 | + |
| 166 | +1. **Unit Tests**: Test individual functions |
| 167 | +2. **Integration Tests**: Test validator interactions |
| 168 | +3. **Property Tests**: Test invariants and properties |
| 169 | +4. **Edge Cases**: Test boundary conditions |
| 170 | + |
| 171 | +### Test Structure |
| 172 | + |
| 173 | +```aiken |
| 174 | +test test_function_name() { |
| 175 | + // Setup |
| 176 | + let input = create_test_input() |
| 177 | +
|
| 178 | + // Execute |
| 179 | + let result = function_under_test(input) |
| 180 | +
|
| 181 | + // Assert |
| 182 | + result == expected_output |
| 183 | +} |
| 184 | +``` |
| 185 | + |
| 186 | +### Testing Best Practices |
| 187 | + |
| 188 | +- **Test Coverage**: Aim for 100% coverage of public functions |
| 189 | +- **Edge Cases**: Test boundary conditions and error cases |
| 190 | +- **Property Testing**: Use property-based testing for complex logic |
| 191 | +- **Integration Testing**: Test validator interactions thoroughly |
| 192 | +- **Mock Data**: Use realistic test data that matches production scenarios |
| 193 | + |
| 194 | +### Running Tests |
| 195 | + |
| 196 | +```bash |
| 197 | +# Run all tests |
| 198 | +cd oada |
| 199 | +aiken test |
| 200 | + |
| 201 | +# Run tests in watch mode |
| 202 | +aiken test --watch |
| 203 | + |
| 204 | +# Run specific test file |
| 205 | +aiken test validators/donate_soada.ak |
| 206 | + |
| 207 | +# Run tests with coverage |
| 208 | +aiken test --coverage |
| 209 | +``` |
| 210 | + |
| 211 | +## 🔒 Security Considerations |
| 212 | + |
| 213 | +### Input Validation |
| 214 | + |
| 215 | +- Validate all inputs thoroughly |
| 216 | +- Check for malicious or unexpected data |
| 217 | +- Implement proper bounds checking |
| 218 | +- Validate cryptographic signatures |
| 219 | + |
| 220 | +### Access Control |
| 221 | + |
| 222 | +- Implement proper authorization checks |
| 223 | +- Use whitelists for privileged operations |
| 224 | +- Verify signatories for sensitive actions |
| 225 | +- Implement role-based access control |
| 226 | + |
| 227 | +### Resource Limits |
| 228 | + |
| 229 | +- Set appropriate limits for operations |
| 230 | +- Prevent resource exhaustion attacks |
| 231 | +- Implement rate limiting where applicable |
| 232 | +- Monitor gas consumption |
| 233 | + |
| 234 | +### Audit Trail |
| 235 | + |
| 236 | +- Maintain clear transaction logs |
| 237 | +- Include sufficient context in redeemers |
| 238 | +- Log important state changes |
| 239 | +- Enable transaction tracing |
| 240 | + |
| 241 | +### Common Security Patterns |
| 242 | + |
| 243 | +#### Authorization Check |
| 244 | + |
| 245 | +```aiken |
| 246 | +fn check_authorization(required_key: KeyHash, ctx: ScriptContext) -> Bool { |
| 247 | + list.has(ctx.transaction.extra_signatories, required_key) |
| 248 | +} |
| 249 | +``` |
| 250 | + |
| 251 | +#### Value Validation |
| 252 | + |
| 253 | +```aiken |
| 254 | +fn validate_value(amount: Int, min: Int, max: Int) -> Bool { |
| 255 | + and{ |
| 256 | + amount >= min, |
| 257 | + amount <= max |
| 258 | + } |
| 259 | +} |
| 260 | +``` |
| 261 | + |
| 262 | +#### State Transition Validation |
| 263 | + |
| 264 | +```aiken |
| 265 | +fn validate_state_transition(old_state: State, new_state: State) -> Bool { |
| 266 | + // Ensure state transitions are valid |
| 267 | + and{ |
| 268 | + new_state.version > old_state.version, |
| 269 | + new_state.timestamp > old_state.timestamp, |
| 270 | + // Add other validation rules |
| 271 | + } |
| 272 | +} |
| 273 | +``` |
| 274 | + |
| 275 | +## 🤝 Contributing |
| 276 | + |
| 277 | +### Development Workflow |
| 278 | + |
| 279 | +1. **Fork the repository** |
| 280 | +2. **Create a feature branch**: `git checkout -b feature/your-feature` |
| 281 | +3. **Make your changes** following the development guidelines |
| 282 | +4. **Add tests** for new functionality |
| 283 | +5. **Run the test suite**: `aiken test` |
| 284 | +6. **Submit a pull request** |
| 285 | + |
| 286 | +### Pull Request Guidelines |
| 287 | + |
| 288 | +1. **Clear description** of changes |
| 289 | +2. **Reference related issues** |
| 290 | +3. **Include tests** for new functionality |
| 291 | +4. **Update documentation** if needed |
| 292 | +5. **Ensure all tests pass** |
| 293 | + |
| 294 | +### Code Review Process |
| 295 | + |
| 296 | +1. **Automated checks** must pass |
| 297 | +2. **At least one review** from maintainers |
| 298 | +3. **Address feedback** before merging |
| 299 | +4. **Squash commits** for clean history |
| 300 | + |
| 301 | +### Commit Message Guidelines |
| 302 | + |
| 303 | +Use conventional commit format: |
| 304 | + |
| 305 | +``` |
| 306 | +type(scope): description |
| 307 | +
|
| 308 | +[optional body] |
| 309 | +
|
| 310 | +[optional footer] |
| 311 | +``` |
| 312 | + |
| 313 | +Types: |
| 314 | + |
| 315 | +- `feat`: New feature |
| 316 | +- `fix`: Bug fix |
| 317 | +- `docs`: Documentation changes |
| 318 | +- `style`: Code style changes |
| 319 | +- `refactor`: Code refactoring |
| 320 | +- `test`: Test changes |
| 321 | +- `chore`: Build/tooling changes |
| 322 | + |
| 323 | +### Code Review Checklist |
| 324 | + |
| 325 | +- [ ] Code follows style guidelines |
| 326 | +- [ ] Tests are included and passing |
| 327 | +- [ ] Documentation is updated |
| 328 | +- [ ] Security considerations addressed |
| 329 | +- [ ] Performance impact considered |
| 330 | +- [ ] Error handling implemented |
| 331 | +- [ ] Edge cases covered |
| 332 | + |
| 333 | +## 📚 Additional Resources |
| 334 | + |
| 335 | +- [Aiken Documentation](https://aiken-lang.org/) |
| 336 | +- [Cardano Developer Portal](https://developers.cardano.org/) |
| 337 | +- [Plutus Documentation](https://plutus.readthedocs.io/) |
| 338 | +- [Aiken Style Guide](https://aiken-lang.org/style-guide) |
| 339 | + |
| 340 | +## 📄 License |
| 341 | + |
| 342 | +This project is licensed under the MIT License - see the [LICENSE.md](../LICENSE.md) file for details. |
| 343 | + |
| 344 | +## 🆘 Getting Help |
| 345 | + |
| 346 | +- **Issues**: [GitHub Issues](https://github.com/OptimFinance/clean-code/issues) |
| 347 | +- **Discussions**: [GitHub Discussions](https://github.com/OptimFinance/clean-code/discussions) |
| 348 | + |
| 349 | +--- |
| 350 | + |
| 351 | +**Note**: These guidelines are living documents. Please contribute improvements and updates as the project evolves. |
0 commit comments