@@ -1334,6 +1334,7 @@ func (app *App) ProcessTxsSynchronousGiga(ctx sdk.Context, txs [][]byte, typedTx
13341334
13351335 txResults := make ([]* abci.ExecTxResult , len (txs ))
13361336 for i , tx := range txs {
1337+ fmt .Println ("GIGA WORKING tx" , absoluteTxIndices [i ])
13371338 ctx = ctx .WithTxIndex (absoluteTxIndices [i ])
13381339 evmMsg := app .GetEVMMsg (typedTxs [i ])
13391340 // If not an EVM tx, fall back to v2 processing
@@ -1691,7 +1692,14 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
16911692 }, nil
16921693 }
16931694
1695+ // Prepare context for EVM transaction (set infinite gas meter like original flow)
1696+ // Use a fresh EventManager to collect ALL events during this transaction
1697+ ctx = ctx .WithGasMeter (sdk .NewInfiniteGasMeterWithMultiplier (ctx ))
1698+ ctx = ctx .WithTxIndex (txIndex )
1699+ ctx = ctx .WithEventManager (sdk .NewEventManager ())
1700+
16941701 // Associate the address if not already associated (same as EVMPreprocessDecorator)
1702+ // This emits address_associated event
16951703 if _ , isAssociated := app .EvmKeeper .GetEVMAddress (ctx , seiAddr ); ! isAssociated {
16961704 associateHelper := helpers .NewAssociationHelper (& app .EvmKeeper , app .BankKeeper , & app .AccountKeeper )
16971705 if err := associateHelper .AssociateAddresses (ctx , seiAddr , sender , pubkey ); err != nil {
@@ -1702,11 +1710,7 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
17021710 }
17031711 }
17041712
1705- // Prepare context for EVM transaction (set infinite gas meter like original flow)
1706- ctx = ctx .WithGasMeter (sdk .NewInfiniteGasMeterWithMultiplier (ctx ))
1707- ctx = ctx .WithTxIndex (txIndex )
1708-
1709- // Create state DB for this transaction
1713+ // Create state DB for this transaction (uses ctx with our EventManager)
17101714 stateDB := evmstate .NewDBImpl (ctx , & app .EvmKeeper , false )
17111715 defer stateDB .Cleanup ()
17121716
@@ -1726,11 +1730,29 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
17261730 sstore := app .EvmKeeper .GetParams (ctx ).SeiSstoreSetGasEip2200
17271731 cfg := evmtypes .DefaultChainConfig ().EthereumConfigWithSstore (app .EvmKeeper .ChainID (ctx ), & sstore )
17281732
1733+ // Pre-charge gas fee (like V2 ante handler does)
1734+ // This emits gas-related events BEFORE message execution, matching V2's event order
1735+ evmMsg := app .EvmKeeper .GetEVMMessage (ctx , ethTx , sender )
1736+ preChargeEVM := vm .NewEVM (* blockCtx , stateDB , cfg , vm.Config {}, app .EvmKeeper .CustomPrecompiles (ctx ))
1737+ preChargeEVM .SetTxContext (core .NewEVMTxContext (evmMsg ))
1738+ preChargeST := core .NewStateTransition (preChargeEVM , evmMsg , & gp , false , false ) // feeCharged=false to call BuyGas
1739+ if buyGasErr := preChargeST .BuyGas (); buyGasErr != nil {
1740+ return & abci.ExecTxResult {
1741+ Code : 1 ,
1742+ Log : fmt .Sprintf ("failed to buy gas: %v" , buyGasErr ),
1743+ }, nil
1744+ }
1745+
1746+ // Record the count of "ante" events (association + gas charging)
1747+ // In V2, these events appear BEFORE message:action
1748+ anteEventCount := len (ctx .EventManager ().Events ())
1749+
17291750 // Create Giga executor VM
17301751 gigaExecutor := gigaexecutor .NewGethExecutor (* blockCtx , stateDB , cfg , vm.Config {}, gigaprecompiles .AllCustomPrecompilesFailFast )
17311752
1732- // Execute the transaction through giga VM
1733- execResult , execErr := gigaExecutor .ExecuteTransaction (ethTx , sender , app .EvmKeeper .GetBaseFee (ctx ), & gp )
1753+ // Execute the transaction with feeCharged=true since we already charged gas above
1754+ // This prevents double-charging and ensures gas events are in "ante" position
1755+ execResult , execErr := gigaExecutor .ExecuteTransactionWithOptions (ethTx , sender , app .EvmKeeper .GetBaseFee (ctx ), & gp , true , true )
17341756 if execErr != nil {
17351757 return & abci.ExecTxResult {
17361758 Code : 1 ,
@@ -1759,19 +1781,7 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
17591781 vmError = execResult .Err .Error ()
17601782 }
17611783
1762- // Create core.Message from ethTx for WriteReceipt
1763- // WriteReceipt needs msg for GasPrice, To, From, Data, Nonce fields
1764- evmMsg := & core.Message {
1765- Nonce : ethTx .Nonce (),
1766- GasLimit : ethTx .Gas (),
1767- GasPrice : ethTx .GasPrice (),
1768- GasFeeCap : ethTx .GasFeeCap (),
1769- GasTipCap : ethTx .GasTipCap (),
1770- To : ethTx .To (),
1771- Value : ethTx .Value (),
1772- Data : ethTx .Data (),
1773- From : sender ,
1774- }
1784+ // WriteReceipt uses the evmMsg created earlier for gas pre-charge
17751785 receipt , rerr := app .EvmKeeper .WriteReceipt (ctx , stateDB , evmMsg , uint32 (ethTx .Type ()), ethTx .Hash (), execResult .UsedGas , vmError )
17761786 if rerr != nil {
17771787 return & abci.ExecTxResult {
@@ -1799,12 +1809,62 @@ func (app *App) executeEVMTxWithGigaExecutor(ctx sdk.Context, txIndex int, msg *
17991809 // isn't committed, so we pass the receipt through the response for later processing.
18001810 receiptBytes , _ := receipt .Marshal ()
18011811
1812+ // Collect all events from the EventManager
1813+ // In V2, events are structured as: anteEvents + message:action + msgResult.Events
1814+ // We insert message:action at the correct position (after ante events)
1815+ eventMsgName := sdk .MsgTypeURL (msg )
1816+ allEventsSlice := ctx .EventManager ().Events ()
1817+
1818+ // Split events: ante events (before execution) and exec events (during execution)
1819+ // IMPORTANT: Make copies to avoid slice aliasing issues with append
1820+ anteEvents := make (sdk.Events , anteEventCount )
1821+ copy (anteEvents , allEventsSlice [:anteEventCount ])
1822+ execEvents := make (sdk.Events , len (allEventsSlice )- anteEventCount )
1823+ copy (execEvents , allEventsSlice [anteEventCount :])
1824+
1825+ // Check if anteEvents or execEvents already contains a message:action event
1826+ // (This can happen if the execution path emits one internally)
1827+ hasMessageAction := false
1828+ for _ , e := range allEventsSlice {
1829+ if e .Type == sdk .EventTypeMessage {
1830+ for _ , attr := range e .Attributes {
1831+ if string (attr .Key ) == sdk .AttributeKeyAction {
1832+ hasMessageAction = true
1833+ break
1834+ }
1835+ }
1836+ }
1837+ if hasMessageAction {
1838+ break
1839+ }
1840+ }
1841+
1842+ // Build final events: anteEvents + message:action + execEvents (matches V2 exactly)
1843+ // Only add message:action if not already present
1844+ var allEvents sdk.Events
1845+ if hasMessageAction {
1846+ // message:action already exists, just combine without adding another
1847+ allEvents = anteEvents .AppendEvents (execEvents )
1848+ } else {
1849+ // Insert message:action between ante and exec events
1850+ msgActionEvent := sdk.Events {
1851+ sdk .NewEvent (sdk .EventTypeMessage , sdk .NewAttribute (sdk .AttributeKeyAction , eventMsgName )),
1852+ }
1853+ allEvents = anteEvents .AppendEvents (msgActionEvent ).AppendEvents (execEvents )
1854+ }
1855+
1856+ // Create message log (same format as RunMsgs)
1857+ msgLogs := sdk.ABCIMessageLogs {
1858+ sdk .NewABCIMessageLog (uint32 (0 ), vmError , allEvents ),
1859+ }
1860+
18021861 //nolint:gosec // G115: safe, UsedGas won't exceed int64 max
18031862 return & abci.ExecTxResult {
18041863 Code : code ,
18051864 Data : receiptBytes ,
18061865 GasUsed : int64 (execResult .UsedGas ),
1807- Log : vmError ,
1866+ Log : strings .TrimSpace (msgLogs .String ()),
1867+ Events : sdk .MarkEventsToIndex (allEvents .ToABCIEvents (), app .IndexEvents ),
18081868 EvmTxInfo : & abci.EvmTxInfo {
18091869 TxHash : ethTx .Hash ().Hex (),
18101870 VmError : vmError ,
0 commit comments