/
GasPriceOracle.sol
185 lines (169 loc) · 6.07 KB
/
GasPriceOracle.sol
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Semver } from "../universal/Semver.sol";
import { Predeploys } from "../libraries/Predeploys.sol";
import { L1Block } from "../L2/L1Block.sol";
/**
* @custom:proxied
* @custom:predeploy 0x420000000000000000000000000000000000000F
* @title GasPriceOracle
* @notice This contract maintains the variables responsible for computing the L1 portion of the
* total fee charged on L2. Before Bedrock, this contract held variables in state that were
* read during the state transition function to compute the L1 portion of the transaction
* fee. After Bedrock, this contract now simply proxies the L1Block contract, which has
* the values used to compute the L1 portion of the fee in its state.
*
* The contract exposes an API that is useful for knowing how large the L1 portion of the
* transaction fee will be. The following events were deprecated with Bedrock:
* - event OverheadUpdated(uint256 overhead);
* - event ScalarUpdated(uint256 scalar);
* - event DecimalsUpdated(uint256 decimals);
*/
contract GasPriceOracle is Semver {
/**
* @notice Number of decimals used in the scalar.
*/
uint256 public constant DECIMALS = 6;
uint256 public tokenRatio;
address public owner;
address public operator;
/**
* @custom:semver 1.0.0
*/
constructor() Semver(1, 0, 0) {}
/**********
* Events *
**********/
event TokenRatioUpdated(uint256 indexed previousTokenRatio, uint256 indexed newTokenRatio);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event OperatorUpdated(address indexed previousOperator, address indexed newOperator);
/**********
* Modifiers *
**********/
modifier onlyOwner() {
require(owner == msg.sender, "Caller is not the owner");
_;
}
modifier onlyOperator() {
require(operator == msg.sender, "Caller is not the operator");
_;
}
/**
* Allows the owner to modify the operator.
* @param _operator New operator
*/
// slither-disable-next-line external-function
function setOperator(address _operator) public onlyOwner {
address previousOperator = operator;
operator = _operator;
emit OperatorUpdated(previousOperator, operator);
}
/**
* @dev Transfers ownership of the contract to a new account (`_owner`).
* Can only be called by the current owner.
*/
function transferOwnership(address _owner) public onlyOwner {
require(_owner != address(0), "new owner is the zero address");
address previousOwner = owner;
owner = _owner;
emit OwnershipTransferred(previousOwner, owner);
}
/**
* Allows the operator to modify the token ratio.
* @param _tokenRatio New tokenRatio
*/
// slither-disable-next-line external-function
function setTokenRatio(uint256 _tokenRatio) public onlyOperator {
uint256 previousTokenRatio = _tokenRatio;
tokenRatio = _tokenRatio;
emit TokenRatioUpdated(previousTokenRatio, tokenRatio);
}
/**
* @notice Computes the L1 portion of the fee based on the size of the rlp encoded input
* transaction, the current L1 base fee, and the various dynamic parameters.
*
* @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.
*
* @return L1 fee that should be paid for the tx
*/
function getL1Fee(bytes memory _data) external view returns (uint256) {
uint256 l1GasUsed = getL1GasUsed(_data);
uint256 l1Fee = l1GasUsed * l1BaseFee();
uint256 divisor = 10**DECIMALS;
uint256 unscaled = l1Fee * scalar();
uint256 scaled = unscaled / divisor;
return scaled;
}
/**
* @notice Retrieves the current gas price (base fee).
*
* @return Current L2 gas price (base fee).
*/
function gasPrice() public view returns (uint256) {
return block.basefee;
}
/**
* @notice Retrieves the current base fee.
*
* @return Current L2 base fee.
*/
function baseFee() public view returns (uint256) {
return block.basefee;
}
/**
* @notice Retrieves the current fee overhead.
*
* @return Current fee overhead.
*/
function overhead() public view returns (uint256) {
return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();
}
/**
* @notice Retrieves the current fee scalar.
*
* @return Current fee scalar.
*/
function scalar() public view returns (uint256) {
return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();
}
/**
* @notice Retrieves the latest known L1 base fee.
*
* @return Latest known L1 base fee.
*/
function l1BaseFee() public view returns (uint256) {
return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();
}
/**
* @custom:legacy
* @notice Retrieves the number of decimals used in the scalar.
*
* @return Number of decimals used in the scalar.
*/
function decimals() public pure returns (uint256) {
return DECIMALS;
}
/**
* @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which
* represents the per-transaction gas overhead of posting the transaction and state
* roots to L1. Adds 68 bytes of padding to account for the fact that the input does
* not have a signature.
*
* @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.
*
* @return Amount of L1 gas used to publish the transaction.
*/
function getL1GasUsed(bytes memory _data) public view returns (uint256) {
uint256 total = 0;
uint256 length = _data.length;
for (uint256 i = 0; i < length; i++) {
if (_data[i] == 0) {
total += 4;
} else {
total += 16;
}
}
uint256 unsigned = total + overhead();
return unsigned + (68 * 16);
}
}