1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* Fee related serialization and deserialization
*/
import { BigNumber } from '@ethersproject/bignumber'
import { remove0x } from '../common'
export const txDataZeroGas = 4
export const txDataNonZeroGasEIP2028 = 16
const big10 = BigNumber.from(10)
export const scaleDecimals = (
value: number | BigNumber,
decimals: number | BigNumber
): BigNumber => {
value = BigNumber.from(value)
decimals = BigNumber.from(decimals)
// 10**decimals
const divisor = big10.pow(decimals)
return value.div(divisor)
}
// data is the RLP encoded unsigned transaction
export const calculateL1GasUsed = (
data: string | Buffer,
overhead: number | BigNumber
): BigNumber => {
const [zeroes, ones] = zeroesAndOnes(data)
const zeroesCost = zeroes * txDataZeroGas
// Add a buffer to account for the signature
const onesCost = (ones + 68) * txDataNonZeroGasEIP2028
return BigNumber.from(onesCost).add(zeroesCost).add(overhead)
}
export const calculateL1Fee = (
data: string | Buffer,
overhead: number | BigNumber,
l1GasPrice: number | BigNumber,
scalar: number | BigNumber,
decimals: number | BigNumber
): BigNumber => {
const l1GasUsed = calculateL1GasUsed(data, overhead)
const l1Fee = l1GasUsed.mul(l1GasPrice)
const scaled = l1Fee.mul(scalar)
const result = scaleDecimals(scaled, decimals)
return result
}
// Count the number of zero bytes and non zero bytes in a buffer
export const zeroesAndOnes = (data: Buffer | string): Array<number> => {
if (typeof data === 'string') {
data = Buffer.from(remove0x(data), 'hex')
}
let zeros = 0
let ones = 0
for (const byte of data) {
if (byte === 0) {
zeros++
} else {
ones++
}
}
return [zeros, ones]
}
/**
* Computes the L1 calldata cost of bytes based
* on the London hardfork.
*
* @param data {Buffer|string} Bytes
* @returns {BigNumber} Gas consumed by the bytes
*/
export const calldataCost = (data: Buffer | string): BigNumber => {
const [zeros, ones] = zeroesAndOnes(data)
const zeroCost = BigNumber.from(zeros).mul(txDataZeroGas)
const nonZeroCost = BigNumber.from(ones).mul(txDataNonZeroGasEIP2028)
return zeroCost.add(nonZeroCost)
}