diff --git a/core/state_transition.go b/core/state_transition.go index 082254e31..78d648ffc 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -332,7 +332,7 @@ func (st *StateTransition) buyAltTokenGas() error { if feeVaultAddress == nil || bytes.Equal(feeVaultAddress.Bytes(), common.Address{}.Bytes()) { return fmt.Errorf("fee vault address is not configured") } - if err := st.TransferAltTokenHybrid(tokenInfo.TokenAddress, st.msg.From(), *feeVaultAddress, tokenFee, tokenInfo.BalanceSlot, tokenBalance); err != nil { + if err = st.TransferAltTokenHybrid(tokenInfo, st.msg.From(), *feeVaultAddress, tokenFee, tokenBalance); err != nil { return fmt.Errorf("failed to transfer alt tokens for gas payment: %v", err) } @@ -682,11 +682,10 @@ func (st *StateTransition) refundGas(refundQuotient uint64) { } tokenAmount := types.EthToAlt(remaining, st.feeRate, st.tokenScale) if err = st.TransferAltTokenHybrid( - tokenInfo.TokenAddress, + tokenInfo, *st.evm.ChainConfig().Morph.FeeVaultAddress, st.msg.From(), tokenAmount, - tokenInfo.BalanceSlot, nil, ); err != nil { log.Error("Failed to refund alt token gas", "tokenID", st.msg.FeeTokenID(), "tokenAddress", tokenInfo.TokenAddress.Hex(), "amount", tokenAmount, "error", err) diff --git a/core/token_gas.go b/core/token_gas.go index 37df0df6a..88d2cb96d 100644 --- a/core/token_gas.go +++ b/core/token_gas.go @@ -28,7 +28,7 @@ func (st *StateTransition) GetAltTokenBalanceHybrid(tokenID uint16, user common. return nil, nil, err } balance := new(big.Int) - if info.BalanceSlot == (common.Hash{}) { + if !info.HasSlot { balance, err = GetAltTokenBalanceByEVM(st.evm, info.TokenAddress, user) if err != nil { return nil, nil, err @@ -44,16 +44,16 @@ func (st *StateTransition) GetAltTokenBalanceHybrid(tokenID uint16, user common. // TransferAltTokenHybrid transfers alt tokens using either storage slot or call method // If balanceSlot is zero hash, uses call method; otherwise uses storage slot method -func (st *StateTransition) TransferAltTokenHybrid(tokenAddress, from, to common.Address, amount *big.Int, balanceSlot common.Hash, userBalanceBefore *big.Int) error { +func (st *StateTransition) TransferAltTokenHybrid(tokenInfo *fees.TokenInfo, from, to common.Address, amount *big.Int, userBalanceBefore *big.Int) error { if amount == nil || amount.Cmp(big.NewInt(0)) == 0 { return nil } - if balanceSlot == (common.Hash{}) { + if !tokenInfo.HasSlot { // Use call method - return transferAltTokenByEVM(st.evm, tokenAddress, from, to, amount, userBalanceBefore) + return transferAltTokenByEVM(st.evm, tokenInfo.TokenAddress, from, to, amount, userBalanceBefore) } // Use storage slot method - return fees.TransferAltTokenByState(st.state, tokenAddress, balanceSlot, from, to, amount) + return fees.TransferAltTokenByState(st.state, tokenInfo.TokenAddress, tokenInfo.BalanceSlot, from, to, amount) } // GetAltTokenBalance returns the balance of an alt token for a specific address. diff --git a/rollup/fees/token_info.go b/rollup/fees/token_info.go index a773567b5..24b2dee25 100644 --- a/rollup/fees/token_info.go +++ b/rollup/fees/token_info.go @@ -32,6 +32,7 @@ type TokenInfo struct { IsActive bool Decimals uint8 Scale *big.Int + HasSlot bool } // CalculateUint16MappingSlot calculates the storage slot for a mapping key @@ -105,10 +106,16 @@ func getTokenInfo(state StateDB, contractAddr common.Address, tokenID uint16) (* return nil, fmt.Errorf("token with ID %d not found", tokenID) } + hasSlot := false // Read balanceSlot (offset 1) balanceSlot := CalculateStructFieldSlot(baseSlot, 1) balanceSlotValue := state.GetState(contractAddr, balanceSlot) - + if balanceSlotValue != (common.Hash{}) { + hasSlot = true + slotInt := new(big.Int).SetBytes(balanceSlotValue[:]) + actualSlotInt := new(big.Int).Sub(slotInt, big.NewInt(1)) + balanceSlotValue = common.BigToHash(actualSlotInt) + } // Read isActive and decimals (offset 2) // In Solidity packed storage, bool and uint8 are packed from right to left // isActive (bool) is at byte 31 (rightmost/least significant) @@ -129,6 +136,7 @@ func getTokenInfo(state StateDB, contractAddr common.Address, tokenID uint16) (* IsActive: isActive, Decimals: decimals, Scale: scale, + HasSlot: hasSlot, }, nil }