fix balance check

This commit is contained in:
Sina Mahmoodi 2023-12-13 13:50:04 +03:30
parent 89d79d6d3c
commit 54f4bc741d

View file

@ -236,24 +236,22 @@ func (st *StateTransition) to() common.Address {
} }
func (st *StateTransition) buyGas() error { func (st *StateTransition) buyGas() error {
if st.msg.DynamicFee { if err := st.balanceCheck(); err != nil {
if err := st.buy1559Gas(); err != nil { return err
return err }
} if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
st.buyDynamicFee()
} else { } else {
if err := st.buyLegacyGas(); err != nil { fee := new(big.Int).SetUint64(st.msg.GasLimit)
return err fee = fee.Mul(fee, st.msg.GasPrice)
} // TODO: rename change reason to indicate tip.
st.state.SubBalance(st.msg.From, fee, state.BalanceChangeGasBuy)
} }
if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) { if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) {
if err := st.buyBlobGas(); err != nil { if err := st.buyBlobGas(); err != nil {
return err return err
} }
} }
valueCheck := new(big.Int).Set(st.msg.Value)
if have, want := st.state.GetBalance(st.msg.From), valueCheck; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want)
}
if err := st.gp.SubGas(st.msg.GasLimit); err != nil { if err := st.gp.SubGas(st.msg.GasLimit); err != nil {
return err return err
@ -267,50 +265,44 @@ func (st *StateTransition) buyGas() error {
return nil return nil
} }
func (st *StateTransition) buyLegacyGas() error { // balanceCheck checks the account can pay all they claimed
mgval := new(big.Int).SetUint64(st.msg.GasLimit) // they can pay.
mgval = mgval.Mul(mgval, st.msg.GasPrice) func (st *StateTransition) balanceCheck() error {
balanceCheck := new(big.Int).Set(mgval) balanceCheck := new(big.Int).SetUint64(st.msg.GasLimit)
// GasFeeCap defaults to gas price for legacy txes.
balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap)
balanceCheck = balanceCheck.Add(balanceCheck, st.msg.Value)
if st.msg.BlobGasFeeCap != nil {
blobFee := new(big.Int).SetUint64(st.blobGasUsed())
blobFee = blobFee.Mul(blobFee, st.msg.BlobGasFeeCap)
balanceCheck = balanceCheck.Add(balanceCheck, blobFee)
}
if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 { if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want)
} }
st.state.SubBalance(st.msg.From, mgval, state.BalanceChangeGasBuy)
return nil return nil
} }
// buy1559Gas purchases gas according to EIP-1559 rules. See: // buyDynamicFee purchases gas according to EIP-1559 rules. See:
// https://eips.ethereum.org/EIPS/eip-1559 // https://eips.ethereum.org/EIPS/eip-1559
func (st *StateTransition) buy1559Gas() error { func (st *StateTransition) buyDynamicFee() {
balanceCheck := new(big.Int).SetUint64(st.msg.GasLimit)
balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap)
balanceCheck.Add(balanceCheck, st.msg.Value)
if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want)
}
burnt := new(big.Int).SetUint64(st.msg.GasLimit) burnt := new(big.Int).SetUint64(st.msg.GasLimit)
burnt = burnt.Mul(burnt, st.evm.Context.BaseFee) burnt = burnt.Mul(burnt, st.evm.Context.BaseFee)
// TODO: rename and create new change reason type so it's possible to calculate total fee paid.
st.state.SubBalance(st.msg.From, burnt, state.BalanceChangeBurn) st.state.SubBalance(st.msg.From, burnt, state.BalanceChangeBurn)
effectiveTip := cmath.BigMin(st.msg.GasTipCap, new(big.Int).Sub(st.msg.GasFeeCap, st.evm.Context.BaseFee)) effectiveTip := cmath.BigMin(st.msg.GasTipCap, new(big.Int).Sub(st.msg.GasFeeCap, st.evm.Context.BaseFee))
tipVal := new(big.Int).SetUint64(st.msg.GasLimit) tipVal := new(big.Int).SetUint64(st.msg.GasLimit)
tipVal = tipVal.Mul(tipVal, effectiveTip) tipVal = tipVal.Mul(tipVal, effectiveTip)
// TODO: rename to indicate tip.
st.state.SubBalance(st.msg.From, tipVal, state.BalanceChangeGasBuy) st.state.SubBalance(st.msg.From, tipVal, state.BalanceChangeGasBuy)
return nil
} }
// buyBlobGas purchases blob gas as per: // buyBlobGas purchases blob gas as per:
// https://eips.ethereum.org/EIPS/eip-4844 // https://eips.ethereum.org/EIPS/eip-4844
func (st *StateTransition) buyBlobGas() error { func (st *StateTransition) buyBlobGas() error {
if blobGas := st.blobGasUsed(); blobGas > 0 { if blobGas := st.blobGasUsed(); blobGas > 0 {
// Check that the user has enough funds to cover blobGasUsed * tx.BlobGasFeeCap // Pay for blobGasUsed * effective blob fee
balanceCheck := new(big.Int).SetUint64(blobGas)
balanceCheck.Mul(balanceCheck, st.msg.BlobGasFeeCap)
if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want)
}
// Pay for blobGasUsed * actual blob fee
blobFee := new(big.Int).SetUint64(blobGas) blobFee := new(big.Int).SetUint64(blobGas)
blobFee.Mul(blobFee, st.evm.Context.BlobBaseFee) blobFee.Mul(blobFee, st.evm.Context.BlobBaseFee)
st.state.SubBalance(st.msg.From, blobFee, state.BalanceChangeBurn) st.state.SubBalance(st.msg.From, blobFee, state.BalanceChangeBurn)
@ -515,15 +507,17 @@ func (st *StateTransition) refundGas(refundQuotient uint64) uint64 {
// Return ETH for remaining gas, exchanged at the original rate. // Return ETH for remaining gas, exchanged at the original rate.
gasRemaining := new(big.Int).SetUint64(st.gasRemaining) gasRemaining := new(big.Int).SetUint64(st.gasRemaining)
if st.msg.DynamicFee { if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
// Split into burnt gas and tip gas to refund. // Split into burnt gas and tip gas to refund.
burnt := new(big.Int).Mul(gasRemaining, st.evm.Context.BaseFee) burnt := new(big.Int).Mul(gasRemaining, st.evm.Context.BaseFee)
// TODO: rename to unburnt
st.state.AddBalance(st.msg.From, burnt, state.BalanceChangeBurnRefund) st.state.AddBalance(st.msg.From, burnt, state.BalanceChangeBurnRefund)
effectiveTip := cmath.BigMin(st.msg.GasTipCap, new(big.Int).Sub(st.msg.GasFeeCap, st.evm.Context.BaseFee)) effectiveTip := cmath.BigMin(st.msg.GasTipCap, new(big.Int).Sub(st.msg.GasFeeCap, st.evm.Context.BaseFee))
tip := new(big.Int).Mul(gasRemaining, effectiveTip) tip := new(big.Int).Mul(gasRemaining, effectiveTip)
st.state.AddBalance(st.msg.From, tip, state.BalanceChangeGasRefund) st.state.AddBalance(st.msg.From, tip, state.BalanceChangeGasRefund)
} else { } else {
remaining := new(big.Int).Mul(gasRemaining, st.msg.GasPrice) remaining := new(big.Int).Mul(gasRemaining, st.msg.GasPrice)
// TODO: rename to unusedTip
st.state.AddBalance(st.msg.From, remaining, state.BalanceChangeGasRefund) st.state.AddBalance(st.msg.From, remaining, state.BalanceChangeGasRefund)
} }