-
Notifications
You must be signed in to change notification settings - Fork 464
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
fix: address book undefined entry address #1338
Conversation
Branch preview✅ Deploy successful! https://fix_undefined_address_input--webcore.review-web-core.5afe.dev |
ESLint Summary View Full Report
Report generated by eslint-plus-action |
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'm not sure if we should even overwrite the addressBook with the valid entries instead of always filtering them out.
But as this should not exist outside of dev / QA Safes it's probably also not too important.
The validation is not checking for correct checksums though which is required for our address book entries.
src/store/addressBookSlice.ts
Outdated
@@ -45,6 +47,8 @@ export const selectAllAddressBooks = (state: RootState): AddressBookState => { | |||
export const selectAddressBookByChain = createSelector( | |||
[selectAllAddressBooks, (_, chainId: string) => chainId], | |||
(allAddressBooks, chainId): AddressBook => { | |||
return chainId ? allAddressBooks[chainId] || {} : {} | |||
const chainAddresses = allAddressBooks[chainId] | |||
const validAddresses = pickBy(chainAddresses, (_, key) => ADDRESS_RE.test(key)) |
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 have a function to validate addresses. This additionally validates that addresses are checksummed, which we also expect in our addressbook.
const validAddresses = pickBy(chainAddresses, (_, key) => ADDRESS_RE.test(key)) | |
const validAddresses = pickBy(chainAddresses, (_, key) => validateAddress(key) === undefined) |
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 will not validate the address if it isn't checksummed. I didn't use it because it was filtering out the non-checksummed addresses
src/utils/validation.ts
Outdated
@@ -2,9 +2,8 @@ import chains from '@/config/chains' | |||
import { parsePrefixedAddress, sameAddress, isChecksummedAddress } from './addresses' | |||
import { safeFormatUnits, safeParseUnits } from './formatters' | |||
|
|||
export const ADDRESS_RE = /^0x[0-9a-f]{40}$/i |
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'd move it back into validateAddress because that is the function which always should be used IMO.
If we need a helper that returns a boolean we should add something like
export const isValidAddress = (address: string) => {
return validateAddress(address) === undefined
}
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.
Then we should probably split validateAddress
function because it is doing two things at the moment:
- validating the address format
- validating if checksum
Initially I was using that function but it would filter out any address not checksummed and I think we don't want to go that strict in the AB, right?
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 need a helper that returns a boolean
I think we can use the validation as it is -> returning undefined
if passed all checks
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 checksum every address which gets added to the address book. And if its incorrectly checksummed it will not let you add that address. So I think we should go quite strict.
Some APIs only work with checksummed addresses including our tx service for instance.
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 validate them when added to the AB, and in address inputs, validating also in the selector seems like an overkill. And it's computationally not the fastest.
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've included the checksum validation. Reason being an unchecksummed address might be introduced during a development stage, the same way the corrupted AB with an undefined entry was.
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.
And it's computationally not the fastest.
I didn't experience any degradation of performance but to be fair my AB is not extensively populated.
@@ -54,4 +60,17 @@ describe('addressBookSlice', () => { | |||
'4': { '0x0': 'Charlie', '0x1': 'Dave' }, | |||
}) | |||
}) | |||
|
|||
it('should not return entries with invalid address format', () => { | |||
const initialState = { |
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.
Kudos for adding a test :)
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.
The code looks good!
Did you test in the UI with a bogus AB in LS?
@schmanu so should the selector return only checksummed valid addresses? |
Yes! I was able to reproduce the original error with the slice state I included in the PR description :) but added a unit test nevertheless |
src/utils/validation.ts
Outdated
export const validateAddress = (address: string) => { | ||
const ADDRESS_RE = /^0x[0-9a-f]{40}$/i | ||
const ADDRESS_RE = /^0x[0-9a-f]{40}$/i | ||
export const isAddress = (address: string) => ADDRESS_RE.test(address) | ||
|
||
if (!ADDRESS_RE.test(address)) { |
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 restore it how it was if it's not used.
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.
Looking good now! 🥳
@iamacook I think the address from the example |
Congrats, your important contribution to this open-source project has earned you a GitPOAP! GitPOAP: 2022 Safe Web Core Contributor: Head to gitpoap.io & connect your GitHub account to mint! Learn more about GitPOAPs here. |
What it solves
Resolves #1283
How this PR fixes it
Validates the address book in the selector
How to test it
I've added a unit test for it.
Alternatively, I was testing it locally by setting a faulty
addressBookSlice
initialSate.