Skip to content
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

Merged
merged 12 commits into from
Feb 8, 2024
Merged

[Counterfactual] Safe creation #3180

merged 12 commits into from
Feb 8, 2024

Conversation

usame-algan
Copy link
Member

@usame-algan usame-algan commented Jan 31, 2024

What it solves

Resolves #3179

How this PR fixes it

  • Adjust safe creation flow to create counterfactual safes for 1/1 setups
  • Adds fallbacks for CGW calls so the UI is unblocked
  • Fetches native balance
  • Adds feature flag
  • Uses an incremental saltNonce for all safe deployments

How to test it

  1. Connect your wallet and create a 1/1 safe
  2. Observe no cost on the review screen
  3. Press Create
  4. The dashboard should be immediately visible
  5. There should be no errors
  6. Send ETH to the safe address
  7. Observe it being visible on the assets page
  8. Create another 1/1 safe
  9. Observe the same safe address

Screenshots

Checklist

  • I've tested the branch on mobile 📱
  • I've documented how it affects the analytics (if at all) 📊
  • I've written a unit/e2e test for it (if applicable) 🧑‍💻

Copy link

github-actions bot commented Jan 31, 2024

Copy link

ESLint Summary View Full Report

Annotations are provided inline on the Files Changed tab. You can also see all annotations that were generated on the annotations page.

Type Occurrences Fixable
Errors 0 0
Warnings 0 0
Ignored 0 N/A
  • Result: ✅ success
  • Annotations: 0 total

Report generated by eslint-plus-action

Copy link

github-actions bot commented Jan 31, 2024

📦 Next.js Bundle Analysis for safe-wallet-web

This analysis was generated by the Next.js Bundle Analysis action. 🤖

⚠️ Global Bundle Size Increased

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.

Copy link

github-actions bot commented Jan 31, 2024

Coverage report

St.
Category Percentage Covered / Total
🟡 Statements
78.77% (-0.07% 🔻)
11328/14381
🔴 Branches
56.46% (-0.15% 🔻)
2508/4442
🟡 Functions
63.3% (+0.12% 🔼)
1806/2853
🟢 Lines
80.09% (-0.09% 🔻)
10212/12751
Show new covered files 🐣
St.
File Statements Branches Functions Lines
🔴
... / undeployedSafesSlice.ts
44% 0% 60% 50%
🟡
... / utils.ts
73.08% 60% 60% 72.73%
🟢
... / utils.ts
100% 100% 100% 100%
Show files with reduced coverage 🔻
St.
File Statements Branches Functions Lines
🟢
... / safeCoreSDK.ts
92.16% (-1.72% 🔻)
83.33% (-7.58% 🔻)
100%
93.33% (-2.02% 🔻)
🟢
... / useLoadBalances.ts
93.18% (-1.56% 🔻)
66.67% (-8.33% 🔻)
100%
95% (-2.06% 🔻)
🟢
... / index.tsx
96.15%
50% (-12.5% 🔻)
83.33% 96%
🔴
... / index.tsx
47.87% (-2.13% 🔻)
11.11% (-2.22% 🔻)
10% (+0.91% 🔼)
49.44% (-3.26% 🔻)

Test suite run success

1390 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' })
Copy link
Member

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.

Copy link
Member Author

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
Copy link
Member

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.

Copy link

github-actions bot commented Feb 2, 2024

ESLint Summary View Full Report

Annotations are provided inline on the Files Changed tab. You can also see all annotations that were generated on the annotations page.

Type Occurrences Fixable
Errors 0 0
Warnings 0 0
Ignored 0 N/A
  • Result: ✅ success
  • Annotations: 0 total

Report generated by eslint-plus-action

src/components/new-safe/create/logic/utils.test.ts Outdated Show resolved Hide resolved
@@ -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
Copy link
Member

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?

Copy link
Member

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).

Copy link
Member Author

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.

Copy link
Member

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

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Member Author

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)
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member Author

@usame-algan usame-algan Feb 6, 2024

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.

Copy link
Member

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.

Copy link
Member Author

@usame-algan usame-algan Feb 7, 2024

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

Copy link
Member Author

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',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name: 'undeployedSafe',
name: 'undeployedSafes',

Our other slices are named in plural

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link

github-actions bot commented Feb 6, 2024

ESLint Summary View Full Report

Annotations are provided inline on the Files Changed tab. You can also see all annotations that were generated on the annotations page.

Type Occurrences Fixable
Errors 0 0
Warnings 0 0
Ignored 0 N/A
  • Result: ✅ success
  • Annotations: 0 total

Report generated by eslint-plus-action

@francovenica
Copy link
Contributor

I've checked that the safe is created properly
Transferring tokens to the safe are shown in the assets tab (not in the sidebar, but that's expected for now)
Re-creating the safe gives you the same address. Even clearing the storage creates the same address, which is expected

LGTM

@usame-algan usame-algan merged commit 74ed3ce into dev Feb 8, 2024
15 checks passed
@usame-algan usame-algan deleted the cf-safe-creation branch February 8, 2024 09:56
@github-actions github-actions bot locked and limited conversation to collaborators Feb 8, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Counterfactual] Safe creation flow
4 participants