22/* eslint-disable node/no-missing-import */
33import { HardhatEthersSigner , SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers" ;
44import { expect } from "chai" ;
5- import { BigNumberish , BytesLike , MaxUint256 , ZeroAddress , getBytes } from "ethers" ;
6- import { ethers } from "hardhat" ;
5+ import { BigNumberish , BytesLike , MaxUint256 , ZeroAddress , getAddress , getBytes , toBeHex } from "ethers" ;
6+ import { ethers , network } from "hardhat" ;
77
8- import { EnforcedTxGateway , L1MessageQueue , L2GasPriceOracle , MockCaller } from "../typechain" ;
8+ import { EnforcedTxGateway , L1MessageQueueV2 , MockCaller , SystemConfig } from "../typechain" ;
99
1010describe ( "EnforcedTxGateway.spec" , async ( ) => {
1111 let deployer : HardhatEthersSigner ;
1212 let feeVault : HardhatEthersSigner ;
1313 let signer : HardhatEthersSigner ;
1414
1515 let caller : MockCaller ;
16+ let system : SystemConfig ;
1617 let gateway : EnforcedTxGateway ;
17- let oracle : L2GasPriceOracle ;
18- let queue : L1MessageQueue ;
18+ let queue : L1MessageQueueV2 ;
1919
2020 const deployProxy = async ( name : string , admin : string , args : any [ ] ) : Promise < string > => {
2121 const TransparentUpgradeableProxy = await ethers . getContractFactory ( "TransparentUpgradeableProxy" , deployer ) ;
@@ -28,44 +28,57 @@ describe("EnforcedTxGateway.spec", async () => {
2828 beforeEach ( async ( ) => {
2929 [ deployer , feeVault , signer ] = await ethers . getSigners ( ) ;
3030
31+ const EmptyContract = await ethers . getContractFactory ( "EmptyContract" , deployer ) ;
32+ const empty = await EmptyContract . deploy ( ) ;
33+
3134 const ProxyAdmin = await ethers . getContractFactory ( "ProxyAdmin" , deployer ) ;
3235 const admin = await ProxyAdmin . deploy ( ) ;
3336
34- gateway = await ethers . getContractAt (
35- "EnforcedTxGateway" ,
36- await deployProxy ( "EnforcedTxGateway" , await admin . getAddress ( ) , [ ] ) ,
37- deployer
38- ) ;
37+ const TransparentUpgradeableProxy = await ethers . getContractFactory ( "TransparentUpgradeableProxy" , deployer ) ;
38+ const L1MessageQueueV1 = await ethers . getContractFactory ( "L1MessageQueueV1" , deployer ) ;
39+ const L1MessageQueueV2 = await ethers . getContractFactory ( "L1MessageQueueV2" , deployer ) ;
40+ const EnforcedTxGateway = await ethers . getContractFactory ( "EnforcedTxGateway" , deployer ) ;
3941
40- queue = await ethers . getContractAt (
41- "L1MessageQueue" ,
42- await deployProxy ( "L1MessageQueue" , await admin . getAddress ( ) , [
43- deployer . address ,
44- deployer . address ,
45- await gateway . getAddress ( ) ,
46- ] ) ,
42+ system = await ethers . getContractAt (
43+ "SystemConfig" ,
44+ await deployProxy ( "SystemConfig" , await admin . getAddress ( ) , [ ] ) ,
4745 deployer
4846 ) ;
49-
50- oracle = await ethers . getContractAt (
51- "L2GasPriceOracle" ,
52- await deployProxy ( "L2GasPriceOracle" , await admin . getAddress ( ) , [ ] ) ,
53- deployer
47+ const queueV1Proxy = await TransparentUpgradeableProxy . deploy ( empty . getAddress ( ) , admin . getAddress ( ) , "0x" ) ;
48+ const queueV2Proxy = await TransparentUpgradeableProxy . deploy ( empty . getAddress ( ) , admin . getAddress ( ) , "0x" ) ;
49+ const gatewayProxy = await TransparentUpgradeableProxy . deploy ( empty . getAddress ( ) , admin . getAddress ( ) , "0x" ) ;
50+
51+ const queueV1Impl = await L1MessageQueueV1 . deploy ( deployer . address , deployer . address , gatewayProxy . getAddress ( ) ) ;
52+ const queueV2Impl = await L1MessageQueueV2 . deploy (
53+ deployer . address ,
54+ deployer . address ,
55+ gatewayProxy . getAddress ( ) ,
56+ queueV1Proxy . getAddress ( ) ,
57+ system . getAddress ( )
5458 ) ;
59+ const gatewayImpl = await EnforcedTxGateway . deploy ( queueV2Proxy . getAddress ( ) , feeVault . address ) ;
60+ await admin . upgrade ( queueV1Proxy . getAddress ( ) , queueV1Impl . getAddress ( ) ) ;
61+ await admin . upgrade ( queueV2Proxy . getAddress ( ) , queueV2Impl . getAddress ( ) ) ;
62+ await admin . upgrade ( gatewayProxy . getAddress ( ) , gatewayImpl . getAddress ( ) ) ;
63+
64+ gateway = await ethers . getContractAt ( "EnforcedTxGateway" , await gatewayProxy . getAddress ( ) , deployer ) ;
65+ queue = await ethers . getContractAt ( "L1MessageQueueV2" , await queueV2Proxy . getAddress ( ) , deployer ) ;
5566
5667 const MockCaller = await ethers . getContractFactory ( "MockCaller" , deployer ) ;
5768 caller = await MockCaller . deploy ( ) ;
5869
59- await queue . initialize ( ZeroAddress , ZeroAddress , ZeroAddress , oracle . getAddress ( ) , 10000000 ) ;
60- await gateway . initialize ( queue . getAddress ( ) , feeVault . address ) ;
61- await oracle . initialize ( 21000 , 51000 , 8 , 16 ) ;
62-
63- const Whitelist = await ethers . getContractFactory ( "Whitelist" , deployer ) ;
64- const whitelist = await Whitelist . deploy ( deployer . address ) ;
65-
66- await whitelist . updateWhitelistStatus ( [ deployer . address ] , true ) ;
67- await oracle . updateWhitelist ( whitelist . getAddress ( ) ) ;
68- await oracle . setL2BaseFee ( 1 ) ;
70+ await system . initialize (
71+ deployer . address ,
72+ deployer . address ,
73+ {
74+ maxGasLimit : 1000000 ,
75+ baseFeeOverhead : 10n ** 9n ,
76+ baseFeeScalar : 10n ** 18n ,
77+ } ,
78+ { maxDelayEnterEnforcedMode : 0 , maxDelayMessageQueue : 0 }
79+ ) ;
80+ await queue . initialize ( ) ;
81+ await gateway . initialize ( ) ;
6982 } ) ;
7083
7184 context ( "auth" , async ( ) => {
@@ -77,25 +90,7 @@ describe("EnforcedTxGateway.spec", async () => {
7790 } ) ;
7891
7992 it ( "should revert, when initialize again" , async ( ) => {
80- await expect ( gateway . initialize ( ZeroAddress , ZeroAddress ) ) . to . revertedWith (
81- "Initializable: contract is already initialized"
82- ) ;
83- } ) ;
84-
85- context ( "#updateFeeVault" , async ( ) => {
86- it ( "should revert, when non-owner call" , async ( ) => {
87- await expect ( gateway . connect ( signer ) . updateFeeVault ( ZeroAddress ) ) . to . revertedWith (
88- "Ownable: caller is not the owner"
89- ) ;
90- } ) ;
91-
92- it ( "should succeed" , async ( ) => {
93- expect ( await gateway . feeVault ( ) ) . to . eq ( feeVault . address ) ;
94- await expect ( gateway . updateFeeVault ( deployer . address ) )
95- . to . emit ( gateway , "UpdateFeeVault" )
96- . withArgs ( feeVault . address , deployer . address ) ;
97- expect ( await gateway . feeVault ( ) ) . to . eq ( deployer . address ) ;
98- } ) ;
93+ await expect ( gateway . initialize ( ) ) . to . revertedWith ( "Initializable: contract is already initialized" ) ;
9994 } ) ;
10095
10196 context ( "#setPause" , async ( ) => {
@@ -121,66 +116,102 @@ describe("EnforcedTxGateway.spec", async () => {
121116 ) . to . revertedWith ( "Pausable: paused" ) ;
122117 } ) ;
123118
124- it ( "should revert, when call is not EOA" , async ( ) => {
125- const calldata = gateway . interface . encodeFunctionData ( "sendTransaction(address,uint256,uint256,bytes)" , [
126- signer . address ,
127- 0 ,
128- 0 ,
129- "0x" ,
130- ] ) ;
131- await expect ( caller . callTarget ( gateway . getAddress ( ) , calldata ) ) . to . revertedWith (
132- "Only EOA senders are allowed to send enforced transaction"
133- ) ;
134- } ) ;
135-
136119 it ( "should revert, when insufficient value for fee" , async ( ) => {
137120 const fee = await queue . estimateCrossDomainMessageFee ( 1000000 ) ;
121+ await network . provider . send ( "hardhat_setNextBlockBaseFeePerGas" , [ "0" ] ) ;
138122 await expect (
139123 gateway
140124 . connect ( signer )
141125 [ "sendTransaction(address,uint256,uint256,bytes)" ] ( signer . address , 0 , 1000000 , "0x" , { value : fee - 1n } )
142126 ) . to . revertedWith ( "Insufficient value for fee" ) ;
143127 } ) ;
144128
145- it ( "should revert, when failed to deduct the fee" , async ( ) => {
146- await gateway . updateFeeVault ( gateway . getAddress ( ) ) ;
147- const fee = await queue . estimateCrossDomainMessageFee ( 1000000 ) ;
148- await expect (
149- gateway
150- . connect ( signer )
151- [ "sendTransaction(address,uint256,uint256,bytes)" ] ( signer . address , 0 , 1000000 , "0x" , { value : fee } )
152- ) . to . revertedWith ( "Failed to deduct the fee" ) ;
153- } ) ;
154-
155- it ( "should succeed, no refund" , async ( ) => {
129+ it ( "should succeed, with refund" , async ( ) => {
156130 const fee = await queue . estimateCrossDomainMessageFee ( 1000000 ) ;
157131 const feeVaultBalanceBefore = await ethers . provider . getBalance ( feeVault . address ) ;
158- await expect (
159- gateway
160- . connect ( signer )
161- [ "sendTransaction(address,uint256,uint256,bytes)" ] ( deployer . address , 0 , 1000000 , "0x" , { value : fee } )
162- )
132+ const signerBalanceBefore = await ethers . provider . getBalance ( signer . address ) ;
133+ await network . provider . send ( "hardhat_setNextBlockBaseFeePerGas" , [ "0" ] ) ;
134+ const tx = await gateway
135+ . connect ( signer )
136+ [ "sendTransaction(address,uint256,uint256,bytes)" ] ( deployer . address , 0 , 1000000 , "0x" , { value : fee + 100n } ) ;
137+ await expect ( tx )
163138 . to . emit ( queue , "QueueTransaction" )
164139 . withArgs ( signer . address , deployer . address , 0 , 0 , 1000000 , "0x" ) ;
140+ const receipt = await tx . wait ( ) ;
165141 const feeVaultBalanceAfter = await ethers . provider . getBalance ( feeVault . address ) ;
142+ const signerBalanceAfter = await ethers . provider . getBalance ( signer . address ) ;
166143 expect ( feeVaultBalanceAfter - feeVaultBalanceBefore ) . to . eq ( fee ) ;
144+ expect ( signerBalanceBefore - signerBalanceAfter ) . to . eq ( receipt ! . gasUsed * receipt ! . gasPrice + fee ) ;
145+ } ) ;
146+ } ) ;
147+
148+ context ( "#sendTransaction, by Contract" , async ( ) => {
149+ it ( "should revert, when contract is paused" , async ( ) => {
150+ await gateway . setPause ( true ) ;
151+ await expect (
152+ caller . callTarget (
153+ gateway . getAddress ( ) ,
154+ gateway . interface . encodeFunctionData ( "sendTransaction(address,uint256,uint256,bytes)" , [
155+ signer . address ,
156+ 0 ,
157+ 0 ,
158+ "0x" ,
159+ ] )
160+ )
161+ ) . to . revertedWith ( "Pausable: paused" ) ;
162+ } ) ;
163+
164+ it ( "should revert, when insufficient value for fee" , async ( ) => {
165+ const fee = await queue . estimateCrossDomainMessageFee ( 1000000 ) ;
166+ await network . provider . send ( "hardhat_setNextBlockBaseFeePerGas" , [ "0" ] ) ;
167+ await expect (
168+ caller . callTarget (
169+ gateway . getAddress ( ) ,
170+ gateway . interface . encodeFunctionData ( "sendTransaction(address,uint256,uint256,bytes)" , [
171+ signer . address ,
172+ 0 ,
173+ 1000000 ,
174+ "0x" ,
175+ ] ) ,
176+ { value : fee - 1n }
177+ )
178+ ) . to . revertedWith ( "Insufficient value for fee" ) ;
167179 } ) ;
168180
169181 it ( "should succeed, with refund" , async ( ) => {
170182 const fee = await queue . estimateCrossDomainMessageFee ( 1000000 ) ;
183+ const callerBalanceBefore = await ethers . provider . getBalance ( caller . getAddress ( ) ) ;
171184 const feeVaultBalanceBefore = await ethers . provider . getBalance ( feeVault . address ) ;
172185 const signerBalanceBefore = await ethers . provider . getBalance ( signer . address ) ;
173- const tx = await gateway
186+ await network . provider . send ( "hardhat_setNextBlockBaseFeePerGas" , [ "0" ] ) ;
187+ const sender = getAddress (
188+ "0x" +
189+ toBeHex (
190+ ( BigInt ( await caller . getAddress ( ) ) + BigInt ( "0x1111000000000000000000000000000000001111" ) ) % 2n ** 160n
191+ )
192+ . slice ( 2 )
193+ . padStart ( 40 , "0" )
194+ ) ;
195+ const tx = await caller
174196 . connect ( signer )
175- [ "sendTransaction(address,uint256,uint256,bytes)" ] ( deployer . address , 0 , 1000000 , "0x" , { value : fee + 100n } ) ;
176- await expect ( tx )
177- . to . emit ( queue , "QueueTransaction" )
178- . withArgs ( signer . address , deployer . address , 0 , 0 , 1000000 , "0x" ) ;
197+ . callTarget (
198+ gateway . getAddress ( ) ,
199+ gateway . interface . encodeFunctionData ( "sendTransaction(address,uint256,uint256,bytes)" , [
200+ deployer . address ,
201+ 0 ,
202+ 1000000 ,
203+ "0x" ,
204+ ] ) ,
205+ { value : fee + 100n }
206+ ) ;
207+ await expect ( tx ) . to . emit ( queue , "QueueTransaction" ) . withArgs ( sender , deployer . address , 0 , 0 , 1000000 , "0x" ) ;
179208 const receipt = await tx . wait ( ) ;
209+ const callerBalanceAfter = await ethers . provider . getBalance ( caller . getAddress ( ) ) ;
180210 const feeVaultBalanceAfter = await ethers . provider . getBalance ( feeVault . address ) ;
181211 const signerBalanceAfter = await ethers . provider . getBalance ( signer . address ) ;
212+ expect ( callerBalanceAfter - callerBalanceBefore ) . to . eq ( 100n ) ;
182213 expect ( feeVaultBalanceAfter - feeVaultBalanceBefore ) . to . eq ( fee ) ;
183- expect ( signerBalanceBefore - signerBalanceAfter ) . to . eq ( receipt ! . gasUsed * receipt ! . gasPrice + fee ) ;
214+ expect ( signerBalanceBefore - signerBalanceAfter ) . to . eq ( receipt ! . gasUsed * receipt ! . gasPrice + fee + 100n ) ;
184215 } ) ;
185216 } ) ;
186217
@@ -303,6 +334,7 @@ describe("EnforcedTxGateway.spec", async () => {
303334 it ( "should revert, when insufficient value for fee" , async ( ) => {
304335 const signature = await getSignature ( signer , signer . address , 0 , 1000000 , "0x" ) ;
305336 const fee = await queue . estimateCrossDomainMessageFee ( 1000000 ) ;
337+ await network . provider . send ( "hardhat_setNextBlockBaseFeePerGas" , [ "0" ] ) ;
306338 await expect (
307339 gateway
308340 . connect ( deployer )
@@ -320,32 +352,12 @@ describe("EnforcedTxGateway.spec", async () => {
320352 ) . to . revertedWith ( "Insufficient value for fee" ) ;
321353 } ) ;
322354
323- it ( "should revert, when failed to deduct the fee" , async ( ) => {
324- await gateway . updateFeeVault ( gateway . getAddress ( ) ) ;
325- const signature = await getSignature ( signer , signer . address , 0 , 1000000 , "0x" ) ;
326- const fee = await queue . estimateCrossDomainMessageFee ( 1000000 ) ;
327- await expect (
328- gateway
329- . connect ( deployer )
330- [ "sendTransaction(address,address,uint256,uint256,bytes,uint256,bytes,address)" ] (
331- signer . address ,
332- signer . address ,
333- 0 ,
334- 1000000 ,
335- "0x" ,
336- MaxUint256 ,
337- signature ,
338- signer . address ,
339- { value : fee }
340- )
341- ) . to . revertedWith ( "Failed to deduct the fee" ) ;
342- } ) ;
343-
344355 it ( "should succeed, no refund" , async ( ) => {
345356 const signature = await getSignature ( signer , deployer . address , 0 , 1000000 , "0x" ) ;
346357 const fee = await queue . estimateCrossDomainMessageFee ( 1000000 ) ;
347358 const feeVaultBalanceBefore = await ethers . provider . getBalance ( feeVault . address ) ;
348359 expect ( await gateway . nonces ( signer . address ) ) . to . eq ( 0 ) ;
360+ await network . provider . send ( "hardhat_setNextBlockBaseFeePerGas" , [ "0" ] ) ;
349361 await expect (
350362 gateway
351363 . connect ( deployer )
@@ -391,6 +403,7 @@ describe("EnforcedTxGateway.spec", async () => {
391403 const feeVaultBalanceBefore = await ethers . provider . getBalance ( feeVault . address ) ;
392404 const signerBalanceBefore = await ethers . provider . getBalance ( signer . address ) ;
393405 expect ( await gateway . nonces ( signer . address ) ) . to . eq ( 0 ) ;
406+ await network . provider . send ( "hardhat_setNextBlockBaseFeePerGas" , [ "0" ] ) ;
394407 await expect (
395408 gateway
396409 . connect ( deployer )
@@ -435,6 +448,7 @@ describe("EnforcedTxGateway.spec", async () => {
435448 it ( "should revert, when refund failed" , async ( ) => {
436449 const signature = await getSignature ( signer , signer . address , 0 , 1000000 , "0x1234" ) ;
437450 const fee = await queue . estimateCrossDomainMessageFee ( 1000000 ) ;
451+ await network . provider . send ( "hardhat_setNextBlockBaseFeePerGas" , [ "0" ] ) ;
438452 await expect (
439453 gateway
440454 . connect ( deployer )
0 commit comments