-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug/multisig nonce selection #1516
Conversation
called `nonceWithPending`, which will be the next nonce to use which takes into account all "pending" transactions on the safe
✅ Deploy Preview for fractal-dev ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Knowledge gap question: How does nonceWithPending
fix this bug exactly? I understand as much as it being equal to the tx count on the DAO, so as to somehow eagerly set the nonce of the next tx to that count (+1?). Just not sure sure how/where the flow makes that happen. We can chat about it later (or if it can be easily explained in a comment, I'll take ti)
To consider regarding "Are there any other places where a multisig proposal is prepared, other than the obvious "new proposal" page which has been handled in this PR?": Updating DAO settings still seems to keep the same nonce. But, David mentioned something about submitting a proposal of the same nonce as a currently pending proposal that one might want to invalidate. That works currently, but any other DAO setting update (after an unrelated setting update) is still stuck on the now used up nonce. Probably should separate the two intentions (or cook up a way to reject a proposal without having to manually overwrite it, which sounds like a much bigger lift). What I tried:
|
Sure, I'll try to explain here. ContextSafe contracts utilize an internal Next: the way that Multisig Safes work, is that transactions can be "pending". That means that they haven't been submitted onchain yet, they only exist in the web2 world, and in this API based web2 world all of the necessary signers create their signatures for this potential transaction and they're all aggregated in an API. The data that they're signing (the pending transaction) is all of the data that makes up a Safe transaction, including that We utilize the Safe API to get information about a Safe, including its prior transactions. There are a couple of endpoints that we hit. One of those endpoints tells us the nonce that the next transaction must be. We were currently only using the data from this endpoint. Another endpoint (which we weren't using before), gives us a list of all transactions, including any pending ones. the new ... aaaand typing this out, I realize there will be a bug if a Safe already has two pending transactions with the same nonce (these are conflicting, as only one of them will be able to be broadcast onchain, but it's a totally valid state for the UI). |
Awesome, great call out. I'll go investigate this section of the app. edit: @DarksightKellar if you don't mind trying this again, i hope it's fixed now |
Maybe a better question for the group (@tomstuart123 @Da-Colon @mudrila) is: are there any situations in which we don't want to take into account pending multisig transactions, when crafting new ones? I'm going to assume no, and move forward with that. |
Operating under the assumption that any time in the app we're utilizing the `nonce`, it's because we want to create a proposal. Under this assumption, we'll always want to take "pending transactions" into account. Also, this new code handles the cases in which: - There are no pending transactions - There are multiple pending transactions with the same nonce
…t _not_ using the Safe data from global state
if (!safeInfo) { | ||
reset({ error: true }); | ||
return; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't ever be null/undefined, the catch
and return
will handle any Safe API errors
const address = utils.getAddress(_daoAddress); | ||
const safeInfoResponse = await safeAPI.getSafeInfo(address); | ||
const nextNonce = await safeAPI.getNextNonce(address); | ||
safeInfo = { ...safeInfoResponse, nonce: nextNonce }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Look at that, there's a function right on the Safe API for getting the next nonce.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lool I'm glad you didn't discover this before having to implement it yourself, which led to me understanding a wee bit more what's going on behind the scenes
|
||
const sanitizedDaoAddress = utils.getAddress(_daoAddress); | ||
const safeInfo = await safeAPI.getSafeInfo(sanitizedDaoAddress); | ||
const nextNonce = await safeAPI.getNextNonce(sanitizedDaoAddress); | ||
const safeInfoWithGuard = { ...safeInfo, nonce: nextNonce }; | ||
|
||
const node: FractalNode = Object.assign(graphNodeInfo, { | ||
daoName, | ||
safe, | ||
fractalModules, | ||
daoName: await getDaoName(sanitizedDaoAddress, graphNodeInfo.daoName), | ||
safe: safeInfoWithGuard, | ||
fractalModules: await lookupModules(safeInfo.modules), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a place where we're loading up Safe data and not getting it from / putting it into global state, so want to make sure to put the proper next nonce on this one.
src/hooks/DAO/useClawBack.ts
Outdated
|
||
const santitizedParentAddress = utils.getAddress(parentAddress); | ||
const parentSafeInfo = await safeAPI.getSafeInfo(santitizedParentAddress); | ||
const parentSafeNextNonce = await safeAPI.getNextNonce(santitizedParentAddress); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a place where we're loading up Safe data and not getting it from / putting it into global state, so want to make sure to put the proper next nonce on this one.
Hey @adamgall , thanks for this So tested a few proposals with this at this DAO - https://deploy-preview-1516.app.dev.fractalframework.xyz/home?dao=sep:0x463e491e72f20ba1bD70EF79d0D7a777Fd762Fa4 What worked:
What didn't work:
@adamgall can you confirm if this is intended behaviour |
@tomstuart123 the "debatable" behavior you described is not how I intended it to work. looking at your Safe through the Safe's UI tells me that any new proposals being created in Fractal should have a nonce 6. Now, I did explicitly test this, and it was working for me as I just described here. So, not sure what's going on. Care to hop on a call and figure this out? |
Not ready for merge yet, more work to do.
After speaking with @tomstuart123 , there's some more work to do on this branch. The outstanding issue is that we only fetch the "next nonce" once, when a Safe is initially loaded in Fractal. If a transaction is created in Fractal (and not executed), then another transaction is created, that second one will still be using the "next nonce" from the first one. We need to figure out the cleanest way to re-fetch the "next nonce"...
|
The only other thing that comes to mind, is way more tedious but check nonce as things happen.
|
…isig-nonce-selection
@tomstuart123 @Da-Colon @mudrila @DarksightKellar Updated the code so that whenever pulling up the New Proposal page, we re-fetch the Safe Data to make sure the most recent "next nonce" is being used. Still seeing some delay of about a minute after a new proposal is queued up before the nonce updates, but I think that's baked into the caching of our Safe Service client code. This is ready for re-review. |
92a7b8a
to
43253a1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
read through code, saw it live, Ship it!
Additional question. This covers "New Proposal", What about the other spots such as 'Settings' and 'Edit' and Treasury Pages (for Send Assets)? |
dammit |
Some observations:
For the most part these feel like edge case that won't matter in real world use. |
Good notes, thanks @DarksightKellar
Yep, this is a bug (nice find), but out of scope for this PR. I've opened an issue: #1536
These last two points, yeah, not ideal, but not sure how much more I can do about them. |
To Do: Make sure Nonce is updated on Send Tokens proposal creation, too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed with @adamgall that we make the 'auto nonce update without refresh' in other areas of the app in another issue
see here
This PR is approved
https://github.com/orgs/decentdao/projects/32/views/3?pane=issue&itemId=59938098
Closes #1474
Outstanding questions
Testing