Unacceptable relayMaxNonce issue with multiple tests using gsn


I Have a couple of test files where I am utilizing gsn now the issue is when I run my tests the tests in the first file run fine in the 2nd file I get this issue

Relaying errors (1): => Got error response from relay: Unacceptable relayMaxNonce: 3. current nonce: 19

Is this a known issue ?

Is it possible that you restarted the blockchain (and therefore the hub contract, so it expects relays it thinks of as new to have a nonce of zero), but not the relay (which keeps its old nonce)? Or maybe vice versa?

@qbzzt I start ganache at the start and just run truffle test contracts from 1 file pass and other give this error

This situation is VERY strange, and probably means something is mis-configured in your test.

“unacceptable nonce” is expected when the relayer attempt to send many parallel requests.
The client saw the current on-chain relayer’s nonce which was below 3, but the returned signed transaction was with nonce 19 - which means the relayer signed many transactions (which didn’t get mined yet)
While it is possible to have several such signed-but-not-mined requests on real network, but not with ganache which always “auto-mine”

Are your tests based on the sample tests (e.g. in test-with-web3) ?
Probably you’re missing some “await”, and thus try to “bombard” the relayer with many transactions which it can’t handle - though in this case you should first see the error when the nonce gets to 4.

can you share your test script?

@drortirosh the scenario is I have 2 test files if I comment one and then run truffle test everything works fine but if both files are uncommented and I run truffle test then I face this issue the code isn’t open sourced actually each has file has about 4 -8 test cases

I think the problem is that you attempt to start GSN in each script, and end up using the wrong relayer
if you use “startGsn()” from your “before()” block, make sure to call “stopGsn” from the “after” block.
it might be better to start GSN outside of your test script, using

run-with-testrpc 'gsn start'

Which runs both ganache and GSN.
In your code, you get the deployed addresses using:

    let deploymentResult = loadDeployment('./build/gsn')
    let { naivePaymasterAddress, relayHubAddress, forwraderAddress } = deploymentResult

@drortirosh actually i was starting it separately in another terminal with npx gsn start is that not right ?

yes, you do need to run “gsn start” in a separate terminal (btw: it is described so in the tutorial)
but you also must not use gsnStart() in your code, as it creates ANOTHER RelayHub and ANOTHER relayer, which I think was the cause of your nonce mismatch issue (I’ve never seen this “Unacceptable relayMaxNonce” error in any test environment, so I’m trying to figure what is wrong in yours)

can you enable logging (adding logLevel: 0 to your config) and send me the output?

@drortirosh logs from one of the failed tests

relayTransaction response: undefined Unacceptable relayMaxNonce: 3. current nonce: 25
relayTransaction:  {"relayRequest":{"request":{"to":"0xc4ccca624329f3f24ae5aebce34cef8a0cb9cb0d","data":"0x0d0d57a80000000000000000000000000000000000000000000000000000000000000022000000000000000000000000eebb0c0e01cffff680f3640a64f8c51178da1c1000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004ce1b815f00000000000000000000000000000000000000000000000000000000","from":"0x8e18a2e4ca2eb93dd46a751e74d05ca9400277e0","value":"0","nonce":"0","gas":"1000000"},"relayData":{"pctRelayFee":"0","baseRelayFee":"0","gasPrice":"24000000000","paymaster":"0x87aFDcAe0D70Ff005e24392AcdA37F11794d628A","paymasterData":"0x","clientId":"1","forwarder":"0x3Bf584C35352D605aa1F50FaE2CA8290bbd74C9b","relayWorker":"0xdadbd9cd7e5e27a115decb99bfa035cf96591dca"}},"metadata":{"relayHubAddress":"0xa499c2C404E0f125Cb78EB1b374D917a467D719F","signature":"0x1c51ba9b1593897dda08eebcc7f3f497db7b3bf8210db49b614b77d280c4fed00f117dd260e1dad9611f3a5f3b59b576717061790d14d6311786db8d81fb62ea1c","approvalData":"0x","relayMaxNonce":3}}
Failed to relay call. Results:
Relaying errors (1): => Got error response from relay: Unacceptable relayMaxNonce: 3. current nonce: 25

Same error with other failed tests

in the before each of both the files I am basically setting relay hub, setting forwarder and setting up the configuration

Not sure what is “setting the hub” means.
When you use “gsn start”, GSN is all set up, so all you need to do in your code is bring up a RelayProvider

{ relayHubAddress, naivePaymasterAddress, forwarderAddress } = 
gsnConfig = await resolveConfigurationGSN({
     forwarderAddress, paymasterAddress:naivePaymasterAddress })

gsnProvider = new RelayProvider(web3provider, gsnConfig) 

You need the forwarder to update your recipient contract. You usually don’t need the relayHub itself, only the paymaster, since the paymaster is already pre-configured with the right relayHub.
You only need the relayHub itself if you want to deploy your own paymaster.

NOTE: With v2.0.3 (just released…), you no longer need the “resolveConfigurationGSN”, and can pass the configuration directly to the RelayProvider

Yes @drortirosh exactly by setting the hub I meant the configuration and using set relay hub method and transferring eth to paymaster since I have my own custom paymaster.
And since I have 2 test files so doing this in before each of both tests

I tried to reproduce the problem, but I can’t.
I did “gsn start” from one window.
then created several test files, each doing

const depl = GsnTestEnvironment.loadDeployment()
provider = await new RelayProvider( web3.currentProvider, { paymasterAddress: depl.naivePaymasterAddress }).init()

and all tests on both files passed correctly.
So there is nothing inherent to GSN to prevent running tests from multiple files.
If you send over some of your files, I could try to see what the problem is.

I think your issue relate to the fact that you use contract( ... ) construct of truffle.
While its great for testing, it reverts blockchain state, which makes the relayer confused …
My suggestion:

  • change contract(...) construct to context(...)
    The blockchain state will no longer be reverted after the test.
    A side effect that you no longer gets the “accounts” as parameter, so you need to add `before( async()=>{ accounts = await web3.eth.getAccounts() } )

  • Another option is to use startGsn() in each test, bringing its own GSN deployment and relayer

thanks will give this a go

@drortirosh when I use gsnstart in my before block I get this error

TypeError: Cannot assign to read only property 'prepareStackTrace' of function 'function Error() { [native code] }'

Did you call stopGsn() at the after () block?
Alternately, did you try the context () option?

I added this

 afterEach(async() => {
    await gsnTestEnv.GsnTestEnvironment.stopGsn();

but get same error again think this might be compatibility issue with the environment package @opengsn/gsn/dist/GsnTestEnvironment

Not sure what your problem is.
This mode works with the test app “test-with-web3”
to duplicate your environment, I duplicated its single-test file, added useGSN:false to contract creation, and changed the “describe” to “contract” - and it ran all tests of both files.

BTW: I still suggest that you try to run your tests with describe instead of contract.it has the drawback of not cleaning up the blockchain state after each test, but otherwise it works.