@@ -9,7 +9,15 @@ const axios = require("axios");
99const { TruffleLoader, RetryProvider } = require ( "../../packages/package-utils" ) ;
1010const { setupEtherRouter } = require ( "../../helpers/upgradable-contracts" ) ;
1111const { UINT256_MAX , CURR_VERSION } = require ( "../../helpers/constants" ) ;
12- const { web3GetTransaction, currentBlockTime } = require ( "../../helpers/test-helper" ) ;
12+ const {
13+ web3GetTransaction,
14+ currentBlockTime,
15+ stopMining,
16+ startMining,
17+ sleep,
18+ hardhatDropTransaction,
19+ mineBlock,
20+ } = require ( "../../helpers/test-helper" ) ;
1321
1422const MetatransactionBroadcaster = require ( "../../packages/metatransaction-broadcaster/MetatransactionBroadcaster" ) ;
1523const { getMetaTransactionParameters, getPermitParameters, setupColony } = require ( "../../helpers/test-data-generator" ) ;
@@ -379,17 +387,21 @@ contract("Metatransaction broadcaster", (accounts) => {
379387 expect ( balanceAccount2 ) . to . eq . BN ( 1200000 ) ;
380388 const balanceColony = await metaTxToken . balanceOf ( colony . address ) ;
381389 expect ( balanceColony ) . to . eq . BN ( 600000 ) ;
390+
391+ // Check the transactions happened with the hashes returned
392+ const tx1 = await web3GetTransaction ( txHash ) ;
393+ expect ( tx1 . gas ) . to . be . lt . BN ( 500000 ) ;
394+ const tx2 = await web3GetTransaction ( txHash2 ) ;
395+ expect ( tx2 . gas ) . to . be . lt . BN ( 500000 ) ;
382396 } ) ;
383397
384- it ( "a valid transaction is broadcast and mined, even if the broadcaster's nonce manager fell behind " , async function ( ) {
398+ it ( "a nonce collision is resolved correctly " , async function ( ) {
385399 await metaTxToken . unlock ( ) ;
386400 await metaTxToken . mint ( USER0 , 1500000 , { from : USER0 } ) ;
387- await metaTxToken . mint ( USER1 , 1500000 , { from : USER0 } ) ;
388401
389402 const txData = await metaTxToken . contract . methods . transfer ( colony . address , 300000 ) . encodeABI ( ) ;
390403
391404 const { r, s, v } = await getMetaTransactionParameters ( txData , USER0 , metaTxToken . address ) ;
392- const { r : r2 , s : s2 , v : v2 } = await getMetaTransactionParameters ( txData , USER1 , metaTxToken . address ) ;
393405
394406 // Send to endpoint
395407
@@ -402,21 +414,98 @@ contract("Metatransaction broadcaster", (accounts) => {
402414 v,
403415 } ;
404416
405- const res = await axios . post ( "http://127.0.0.1:3000/broadcast" , jsonData , {
417+ await stopMining ( ) ;
418+ const p = new web3 . eth . providers . HttpProvider ( "http://localhost:8545" ) ;
419+
420+ const postRequest = axios . post ( "http://127.0.0.1:3000/broadcast" , jsonData , {
406421 headers : {
407422 "Content-Type" : "application/json" ,
408423 } ,
409424 } ) ;
410425
426+ let firstTxHash = null ;
427+ while ( ! firstTxHash ) {
428+ const block = await provider . send ( "eth_getBlockByNumber" , [ "pending" , true ] ) ;
429+ if ( block . transactions . length > 0 ) {
430+ const [ firstTx ] = block . transactions ;
431+ firstTxHash = firstTx . hash ;
432+ }
433+ await sleep ( 1000 ) ;
434+ }
435+
436+ await hardhatDropTransaction ( p , firstTxHash ) ;
437+
438+ const currentNonce = await provider . getTransactionCount ( USER0 ) ;
439+
440+ await startMining ( ) ;
441+
442+ // This will have the nonce of the dropped transaction, which the broadcaster will try to
443+ // rebroadcast when it sees a block, but it will fail because the nonce is too low
444+ // it should then rebroadcast with the correct nonce
445+ await metaTxToken . mint ( USER1 , 1 , { from : USER0 } ) ;
446+
447+ let newNonce = 0 ;
448+ while ( newNonce < currentNonce + 2 ) {
449+ newNonce = await provider . getTransactionCount ( USER0 ) ;
450+ await mineBlock ( ) ;
451+ await sleep ( 1000 ) ;
452+ }
453+ const res = await postRequest ;
454+
455+ const { txHash } = res . data . data ;
456+ expect ( txHash . length ) . to . be . equal ( 66 ) ;
457+
458+ expect ( res . data ) . to . be . deep . equal ( {
459+ status : "success" ,
460+ data : {
461+ txHash,
462+ } ,
463+ } ) ;
464+
465+ // Check the transaction happened
466+ const balanceAccount1 = await metaTxToken . balanceOf ( USER0 ) ;
467+ expect ( balanceAccount1 ) . to . eq . BN ( 1200000 ) ;
468+ const balanceColony = await metaTxToken . balanceOf ( colony . address ) ;
469+ expect ( balanceColony ) . to . eq . BN ( 300000 ) ;
470+
471+ // Check the transactions happened with the hashes returned
472+ const tx1 = await web3GetTransaction ( txHash ) ;
473+ if ( ! tx1 ) {
474+ throw new Error ( "Transaction not found" ) ;
475+ }
476+ expect ( tx1 . gas ) . to . be . lt . BN ( 500000 ) ;
477+
478+ const originalTx = await web3GetTransaction ( firstTxHash ) ;
479+ expect ( originalTx ) . to . be . null ;
480+ } ) ;
481+
482+ it ( "a valid transaction is broadcast and mined, even if the broadcaster's nonce manager fell behind" , async function ( ) {
483+ await metaTxToken . unlock ( ) ;
484+ await metaTxToken . mint ( USER0 , 1500000 , { from : USER0 } ) ;
485+ await metaTxToken . mint ( USER1 , 1500000 , { from : USER0 } ) ;
486+
487+ const txData = await metaTxToken . contract . methods . transfer ( colony . address , 300000 ) . encodeABI ( ) ;
488+
489+ const { r, s, v } = await getMetaTransactionParameters ( txData , USER0 , metaTxToken . address ) ;
490+
491+ const txCount = await provider . getTransactionCount ( accounts [ 0 ] ) ;
492+ await broadcaster . nonceManager . setTransactionCount ( txCount ) ;
493+
411494 // Make an unexpected transaction
412495 await metaTxToken . mint ( USER2 , 1500000 , { from : USER0 } ) ;
413496
414- jsonData . r = r2 ;
415- jsonData . s = s2 ;
416- jsonData . v = v2 ;
417- jsonData . userAddress = USER1 ;
497+ // Send to endpoint
498+
499+ const jsonData = {
500+ target : metaTxToken . address ,
501+ payload : txData ,
502+ userAddress : USER0 ,
503+ r,
504+ s,
505+ v,
506+ } ;
418507
419- await axios . post ( "http://127.0.0.1:3000/broadcast" , jsonData , {
508+ const res = await axios . post ( "http://127.0.0.1:3000/broadcast" , jsonData , {
420509 headers : {
421510 "Content-Type" : "application/json" ,
422511 } ,
@@ -437,7 +526,11 @@ contract("Metatransaction broadcaster", (accounts) => {
437526 const balanceAccount1 = await metaTxToken . balanceOf ( USER0 ) ;
438527 expect ( balanceAccount1 ) . to . eq . BN ( 1200000 ) ;
439528 const balanceAccount2 = await metaTxToken . balanceOf ( colony . address ) ;
440- expect ( balanceAccount2 ) . to . eq . BN ( 600000 ) ;
529+ expect ( balanceAccount2 ) . to . eq . BN ( 300000 ) ;
530+
531+ // Check the transactions happened with the hashes returned
532+ const tx1 = await web3GetTransaction ( txHash ) ;
533+ expect ( tx1 . gas ) . to . be . lt . BN ( 500000 ) ;
441534 } ) ;
442535
443536 it ( "a valid transaction is broadcast and mined, even if the broadcaster's nonce manager got ahead" , async function ( ) {
@@ -448,7 +541,6 @@ contract("Metatransaction broadcaster", (accounts) => {
448541 const txData = await metaTxToken . contract . methods . transfer ( colony . address , 300000 ) . encodeABI ( ) ;
449542
450543 const { r, s, v } = await getMetaTransactionParameters ( txData , USER0 , metaTxToken . address ) ;
451- const { r : r2 , s : s2 , v : v2 } = await getMetaTransactionParameters ( txData , USER1 , metaTxToken . address ) ;
452544
453545 // Send to endpoint
454546
@@ -461,22 +553,11 @@ contract("Metatransaction broadcaster", (accounts) => {
461553 v,
462554 } ;
463555
464- let res = await axios . post ( "http://127.0.0.1:3000/broadcast" , jsonData , {
465- headers : {
466- "Content-Type" : "application/json" ,
467- } ,
468- } ) ;
469-
470556 // Set the nonce
471557 const txCount = await provider . getTransactionCount ( accounts [ 0 ] ) ;
472558 await broadcaster . nonceManager . setTransactionCount ( txCount + 1 ) ;
473559
474- jsonData . r = r2 ;
475- jsonData . s = s2 ;
476- jsonData . v = v2 ;
477- jsonData . userAddress = USER1 ;
478-
479- res = await axios . post ( "http://127.0.0.1:3000/broadcast" , jsonData , {
560+ const res = await axios . post ( "http://127.0.0.1:3000/broadcast" , jsonData , {
480561 headers : {
481562 "Content-Type" : "application/json" ,
482563 } ,
@@ -497,7 +578,11 @@ contract("Metatransaction broadcaster", (accounts) => {
497578 const balanceAccount1 = await metaTxToken . balanceOf ( USER0 ) ;
498579 expect ( balanceAccount1 ) . to . eq . BN ( 1200000 ) ;
499580 const balanceAccount2 = await metaTxToken . balanceOf ( colony . address ) ;
500- expect ( balanceAccount2 ) . to . eq . BN ( 600000 ) ;
581+ expect ( balanceAccount2 ) . to . eq . BN ( 300000 ) ;
582+
583+ // Check the transaction happened with the hash returned
584+ const tx = await web3GetTransaction ( txHash ) ;
585+ expect ( tx . gas ) . to . be . lt . BN ( 500000 ) ;
501586 } ) ;
502587
503588 it ( "a valid EIP712 transaction is broadcast and mined" , async function ( ) {
@@ -539,6 +624,10 @@ contract("Metatransaction broadcaster", (accounts) => {
539624 // Check the transaction happened
540625 const allowed = await metaTxToken . allowance ( USER0 , colony . address ) ;
541626 expect ( allowed ) . to . eq . BN ( 1 ) ;
627+
628+ // With the expected hash
629+ const tx = await web3GetTransaction ( txHash ) ;
630+ expect ( tx . gas ) . to . be . lt . BN ( 500000 ) ;
542631 } ) ;
543632
544633 it ( "an EIP712 transaction with an invalid spender is not broadcast and mined" , async function ( ) {
@@ -600,26 +689,22 @@ contract("Metatransaction broadcaster", (accounts) => {
600689 s,
601690 v,
602691 } ;
603- try {
604- const res = await axios . post ( "http://127.0.0.1:3000/broadcast" , jsonData , {
605- headers : {
606- "Content-Type" : "application/json" ,
607- } ,
608- } ) ;
692+ const res = await axios . post ( "http://127.0.0.1:3000/broadcast" , jsonData , {
693+ headers : {
694+ "Content-Type" : "application/json" ,
695+ } ,
696+ } ) ;
609697
610- const { txHash } = res . data . data ;
698+ const { txHash } = res . data . data ;
611699
612- expect ( txHash . length ) . to . be . equal ( 66 ) ;
700+ expect ( txHash . length ) . to . be . equal ( 66 ) ;
613701
614- expect ( res . data ) . to . be . deep . equal ( {
615- status : "success" ,
616- data : {
617- txHash,
618- } ,
619- } ) ;
620- } catch ( err ) {
621- console . log ( err . response . data ) ;
622- }
702+ expect ( res . data ) . to . be . deep . equal ( {
703+ status : "success" ,
704+ data : {
705+ txHash,
706+ } ,
707+ } ) ;
623708
624709 // Check the transaction happened
625710 const roles = await colony . getUserRoles ( USER1 , 1 ) ;
@@ -628,6 +713,10 @@ contract("Metatransaction broadcaster", (accounts) => {
628713
629714 const expectedRoles = roleArchitecture | roleFunding ; // eslint-disable-line no-bitwise
630715 expect ( roles ) . to . equal ( ethers . utils . hexZeroPad ( ethers . BigNumber . from ( expectedRoles ) . toHexString ( ) , 32 ) ) ;
716+
717+ // With the expected hash
718+ const tx = await web3GetTransaction ( txHash ) ;
719+ expect ( tx . gas ) . to . be . lt . BN ( 500000 ) ;
631720 } ) ;
632721
633722 it ( "a multicall transaction that calls something invalid is rejected" , async function ( ) {
0 commit comments