Skip to content

Conversation

@sudo-owen
Copy link
Collaborator

No description provided.

claude added 30 commits January 19, 2026 17:47
Initial implementation of sol2ts.py transpiler that converts Solidity
contracts to TypeScript for local simulation of the game engine.

Features:
- Full Solidity lexer/tokenizer with support for all operators and keywords
- Recursive descent parser for Solidity AST
- TypeScript code generation with BigInt support
- Handles structs, enums, contracts, interfaces, functions
- Supports tuple declarations and multi-dimensional arrays
- Basic Yul/inline assembly transpilation (marked as comments)
- Runtime library with storage simulation and bit manipulation helpers

Transpiled files:
- Engine.sol -> Engine.ts (60KB, main game engine)
- StandardAttack.sol, AttackCalculator.sol (move system)
- BasicEffect.sol (effect system)
- Enums.sol, Constants.sol, Structs.sol (data types)
- Add proper Yul code normalization to handle tokenizer spacing
- Implement pattern matching for MonState clearing assembly pattern
- Simplify type casting to use BigInt() without verbose bit masking
- Reduce parentheses in binary operations for cleaner output
- Fix mstore, sload, sstore pattern matching
- Replace name-based heuristics with type registry for array/mapping detection
- Track variable types from declarations (state vars, locals, loop vars)
- Use is_array/is_mapping from TypeName AST for accurate index handling
- Rewrite Yul transpiler with AST-based approach instead of pattern matching
- Handle sload/sstore as generic storage operations (_storageRead/_storageWrite)
- Parse Yul let bindings, if statements, and function calls properly
- Track .slot references to map storage keys to variables
- Add _type_max and _type_min helpers to compute integer type bounds
- Handle type(int32).max, type(uint256).max, etc. in member access
- Transpile Structs.sol to generate TypeScript interfaces
- Transpile Enums.sol, Constants.sol with proper type handling
- Transpile interface files (IEngine, IValidator, IEffect, etc.)
- Re-transpile Engine.sol with updated transpiler
- Remove 161 lines of dead Yul code (old parse_yul_statements,
  transpile_yul_statement, transpile_yul_expression, parse_yul_args,
  transpile_yul_function, transpile_yul_function_expr methods) that
  were superseded by the new AST-based Yul transpiler
- Remove unused self.type_info and self.imports fields from
  TypeScriptCodeGenerator
- Remove unused os import
Generated TypeScript files from the Solidity transpiler should not be
committed as they can be recreated by running the transpiler.
- Add vitest test framework with package.json and config
- Create engine.test.ts with tests for:
  - Battle key computation and consistency
  - Matchmaker authorization
  - MonState packing/unpacking
  - Storage operations
- Update transpiler to:
  - Import from runtime library (Contract, Storage)
  - Extend Contract base class for all classes
  - Add storage helper methods (_getStorageKey, _storageRead, _storageWrite)
  - Handle interface type casts (IMatchmaker(x) -> x)
  - Handle struct constructors (BattleData() -> {} as BattleData)
  - Fix error throwing syntax
- Add module imports from Structs, Enums, Constants for non-self files
- Track known structs, enums, constants, and interfaces for proper prefixing
- Add Structs./Enums./Constants. prefixes to type references
- Handle interfaces as 'any' type in TypeScript
- Add MappingAllocator methods (_initializeStorageKey, _getStorageKey, _freeStorageKey)
- Fix struct constructors to use proper module prefix
- Update Yul transpiler to prefix constant references
- Track current file type to avoid self-referencing prefixes
- Add sha256 and sha256String functions to runtime using Node crypto
- Handle address and bytes32 type casts with proper hex padding
- Convert sha256(abi.encode("string")) to sha256String("string")
- Fix bigint index access by converting to Number() for arrays/mappings
- Add @types/node to tsconfig for Node.js type support
- Update imports to include Enums in Structs.ts
- Remove parens from tuple left-hand side in assignments
- Use empty string instead of '_' for ignored tuple components
- Fix BigInt 'n' suffix check to not strip from variable names like globalLen
- Add decodeAbiParameters to viem imports
- Handle abi.decode with proper argument swapping and type conversion
- Track function parameter types in var_types for proper type inference
- Convert enum values to Number() for viem's encodeAbiParameters (uint8)
- Cast address and bytes32 values to hex string type for viem
- Convert bytes32 casts of computed expressions to hex string format
- Handle small integer types (int32, uint8, etc.) with Number() conversion
- Add hex string type assertion for decodeAbiParameters data argument
- Remove hard-coded MappingAllocator methods from generate_class
- Add storage helpers (_yulStorageKey, _storageRead, _storageWrite) to Contract base class
- Handle contract inheritance using base_contracts from parser
- Track known contract methods for this. prefix handling
- Add function overload handling for TypeScript (merge into optional params)
- Add delete statement parsing and code generation
- Fix mapping key type detection to avoid incorrect Number() conversion
- Import base contracts in generated TypeScript files
When transpiling Yul .slot access and sload/sstore operations, cast storage
variables to 'any' type to handle struct references being used as storage keys.
Update parse_constructor to properly handle nested braces/parens in base
constructor calls (like ATTACK_PARAMS({...})) by tracking parenthesis depth
before looking for the constructor body brace.
- Track inherited state variables from base contracts (known_contract_vars)
- Use ClassName.CONST syntax for static/constant state variables
- Track current class name for static member access
- Add StandardAttack, Ownable, AttackCalculator to known contract methods/vars
- Remove vitest dependency (saves 76 packages)
- Add tsx for running TypeScript tests directly
- Create simple test runner using Node's assert module
- Add scaffold battle test (2v2, speed determines turn order)
- Package-lock reduced from ~5000 to 808 lines
…ting

- Add tracking for library contracts (AttackCalculator) and generate imports
- Fix tuple declaration parsing to preserve trailing comma elements
- Fix enum type casting to use TypeScript type assertions
- Add ATTACK_PARAMS to known structs
- Fix constructor parameter tracking to avoid incorrect this. prefix
- Add current_contract_kind tracking for library static methods
- Remove old vitest-based test file
- Fix tsconfig.json to remove vitest type reference
…optional constructor params

Cleanup improvements:
- Add get_qualified_name() helper to consolidate Structs./Enums./Constants. prefix logic
- Remove unused known_events set (dead code)
- Use helper method in generate_identifier, YUL transpiler, function call generation
- Auto-generate optional constructor parameters for known base classes
- Wrap base class constructor body in conditional for optional params

This reduces code duplication and ensures consistent prefix handling across
different code generation paths.
…nd static const prefixes

- Add BaseConstructorCall AST node and parser support to capture base
  constructor arguments (e.g., StandardAttack(...) in constructor header)
- Generate super() calls with actual arguments instead of empty super()
- Handle struct constructors with named arguments (e.g., ATTACK_PARAMS({...}))
  to generate full object literals instead of empty {} casts
- Fix identifier ordering to check class-local static constants before
  global constants, so BullRush.SELF_DAMAGE_PERCENT is used instead of
  Constants.SELF_DAMAGE_PERCENT
- Add heuristic for internal methods: function calls starting with _ get
  this. prefix when not already present, fixing inherited method calls
…abilities

Tests cover:
- ZapStatus (paralysis): skip turn timing based on priority, auto-removal
- BurnStatus: damage over time (1/16 HP per round)
- Forced switches: user-initiated switches (HitAndDip pattern)
- Forced switches: opponent switches (PistolSquat pattern)
- UpOnly ability: attack boost on damage taken, stacking
- Complex scenarios: burn + ability interaction, multi-turn battles

Includes MockEngine with full effect lifecycle support:
- Effect application and removal
- Round start/end processing
- AfterDamage hooks for abilities
- Stat boost tracking
… literals, and tuple patterns

Parser improvements:
- Add UNCHECKED, TRY, CATCH tokens and keyword handling
- Handle qualified library names in using directives (e.g. EnumerableSetLib.Uint256Set)
- Parse unchecked blocks as regular blocks
- Skip try/catch statements (return empty block)
- Add ArrayLiteral AST node for [val1, val2, ...] syntax
- Fix tuple declaration detection for leading commas (skipped elements)
- Handle qualified type names in variable declarations

Yul transpiler fixes:
- Add _split_yul_args helper for nested parentheses in function args
- Handle caller(), timestamp(), origin() built-in functions
- Add bounds checking for binary operation parsing

These changes enable successful transpilation of:
- GachaRegistry.sol
- BattleHistory.sol
- StatBoosts.sol
- BasicEffect.sol
- StatusEffect.sol and status effect implementations
- Document all resolved parser issues (7 files now transpiling)
- Add Yul transpiler improvements (nested args, built-in functions)
- Document successful base class transpilation (BasicEffect, StatusEffect)
- Update version history with 2026-01-21 changes
- Remove completed items from future work section
Key changes:
- Generate initialization for nested mapping writes (mapping[a][b] = val)
- Add nullish coalescing for compound assignment on mappings (map[k] += val)
- Add default values for mapping reads in variable declarations
- Add mapping helper functions to runtime (mappingGet, mappingEnsure)

These changes enable correct Solidity-style mapping behavior in TypeScript:
- Nested mapping intermediate keys auto-initialize to empty objects
- Compound assignments (+=, -=) on mappings initialize to 0n first
- Reading from non-existent mapping keys returns default values (0n, false, etc.)

Also adds Engine.ts e2e test suite validating:
- Engine instantiation and method availability
- Deterministic battle key computation
- Matchmaker authorization
- Core engine methods (dealDamage, switchActiveMon, addEffect, etc.)

All 29 tests pass (5 unit + 14 e2e + 10 engine-e2e)
- Auto-initialize nested mappings before writes (??= {})
- Auto-initialize before compound assignment on mappings (??= 0n)
- Add default values for mapping reads in variable declarations
- Fix bytes32/address defaults to proper zero hex strings
- Add bit masking for uint type casts < 256 bits
- Add comprehensive engine-e2e.ts test suite (17 tests)
- Create TestableEngine class for proper test initialization
- Mark Engine integration as partially complete
- Add runtime library mapping helpers documentation
- Add Engine E2E test coverage section
- Add EventStream class for capturing contract events
- EventLog interface with name, args, timestamp, emitter, data
- Support filtering: getByName(), filter(), getLast(), has()
- Global globalEventStream shared by all contracts
- Custom streams via setEventStream()/getEventStream()
- Add 5 new tests for EventStream functionality (22 total)
- Update CHANGELOG with event stream documentation
- StatBoosts.ts transpiled for stat modification
- TypeCalculator.ts transpiled for type effectiveness
- All core engine contracts now transpiled
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants