-
Notifications
You must be signed in to change notification settings - Fork 465
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
[Counterfactual] Safe creation #3180
Conversation
Branch preview✅ Deploy successful! |
ESLint Summary View Full Report
Report generated by eslint-plus-action |
📦 Next.js Bundle Analysis for safe-wallet-webThis analysis was generated by the Next.js Bundle Analysis action. 🤖
|
Page | Size (compressed) |
---|---|
global |
1.02 MB (🟡 +944 B) |
Details
The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.
Any third party scripts you have added directly to your app using the <script>
tag are not accounted for in this analysis
If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!
Four Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
Page | Size (compressed) | First Load |
---|---|---|
/balances/nfts |
20.47 KB (🟡 +33 B) |
1.04 MB |
/home |
40.81 KB (🟡 +29 B) |
1.06 MB |
/new-safe/create |
29.93 KB (🟡 +275 B) |
1.05 MB |
/new-safe/load |
19.14 KB (🟡 +34 B) |
1.04 MB |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link
is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script>
tag are not accounted for in this analysis
Next to the size is how much the size has increased or decreased compared with the base branch of this PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this.
Coverage report
Show new covered files 🐣
Show files with reduced coverage 🔻
Test suite run success1390 tests passing in 188 suites. Report generated by 🧪jest coverage report action from ee9496f |
@@ -151,6 +166,41 @@ const ReviewStep = ({ data, onSubmit, onBack, setStep }: StepRenderProps<NewSafe | |||
saltNonce: saltNonce.toString(), | |||
} | |||
|
|||
if (isCounterfactual) { | |||
const counterfactualNonce = await getCounterfactualNonce(provider, { ...props, saltNonce: '0' }) |
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.
If we're switching to an incremental nonce, I would do it for all deployments, not just counterfactual. For the benefitsts that Micah outlined and for consistency.
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.
It would require us to check on-chain if a contract is already deployed to that address for every safe that is created but I think it would simplify our code so I will look into refactoring this part of safe creation a bit more.
@@ -133,6 +145,9 @@ const ReviewStep = ({ data, onSubmit, onBack, setStep }: StepRenderProps<NewSafe | |||
? formatVisualAmount(getTotalFee(maxFeePerGas, maxPriorityFeePerGas, gasLimit), chain?.nativeCurrency.decimals) | |||
: '> 0.001' | |||
|
|||
// Only 1 out of 1 safe setups are supported for now | |||
const isCounterfactual = data.threshold === 1 && data.owners.length === 1 && isCounterfactualEnabled |
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.
Please try to extract all the logic into a service and only do UI rendering in components.
ESLint Summary View Full Report
Report generated by eslint-plus-action |
f165f48
to
a30a045
Compare
9572728
to
e4d6fe7
Compare
ca1af16
to
87fed24
Compare
@@ -117,9 +124,9 @@ const ReviewStep = ({ data, onSubmit, onBack, setStep }: StepRenderProps<NewSafe | |||
return { | |||
owners: data.owners.map((owner) => owner.address), | |||
threshold: data.threshold, | |||
saltNonce, | |||
saltNonce: Date.now(), // Doesn't matter for the gas estimation |
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.
Are you sure about that? I thought the gas cost depend also on how many zeros are in the call data?
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.
I double checked:
A byte of calldata costs either 4 gas (if it is zero) or 16 gas (if it is any other value).
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.
Thanks for checking! In that case I will move the saltNonce calculation into a hook so we can reuse it here.
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.
I think with Date.now() we would get slightly too high gas estimations as the current Date likely contains more zeros then the number incremented by one each time.
So I guess we could also leave it for now. And change the comment slightly
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.
done
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.
I think with Date.now() we would get slightly too high gas estimations as the current Date likely contains more zeros then the number incremented by one each time.
I didn't see this message in time. Just checked and its around a 60 gas difference which I think we can ignore. I reverted the change back and updated the comment instead.
|
||
export const getAvailableSaltNonce = async (provider: BrowserProvider, props: DeploySafeProps): Promise<string> => { | ||
const safeAddress = await computeNewSafeAddress(provider, props) | ||
const isContractDeployed = await isSmartContract(provider, safeAddress) |
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.
Could we not run into Rate Limit issues here? If someone deployed e.g. 10-20 Safes already?
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.
I haven't had any issues so far with around 10 safes created but we should handle possible error responses from the RPC call. In case this becomes an issue with users we could still optimize this e.g. by not incrementally checking saltNonces but using something like binary search.
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.
If the RPC call throws we can't compute a safeAddress
and thus can't create a safe so I would display an error to the user.
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.
Hmm but in that case the user would not be able to create new Safes for that owner right?
If every Safe creation attempts hits the Rate limit, the user will see the error on every attempt. We should experiment if this ever happens by i.e. creating 30 Safes for an owner.
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.
I don't think this will realistically happen. What is the use-case for a wallet to create the exact same safe setup 30 times? I agree though that we should try to limit test it cc. @francovenica
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.
We could also add a fallback to the readonly provider in case the wallet provider fails to increase the chances of success.
const initialState: UndeployedSafeState = {} | ||
|
||
export const undeployedSafeSlice = createSlice({ | ||
name: 'undeployedSafe', |
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.
name: 'undeployedSafe', | |
name: 'undeployedSafes', |
Our other slices are named in plural
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.
done
ESLint Summary View Full Report
Report generated by eslint-plus-action |
b5e32f6
to
e040a48
Compare
8481c7a
to
7b3b385
Compare
dd67f1d
to
095c8b6
Compare
095c8b6
to
ee9496f
Compare
I've checked that the safe is created properly LGTM |
What it solves
Resolves #3179
How this PR fixes it
How to test it
Screenshots
Checklist