-
Notifications
You must be signed in to change notification settings - Fork 679
feat: ERC-7984 Confidential Tokens #3139
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
base: main
Are you sure you want to change the base?
Conversation
|
bugbot run |
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.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
This PR is being reviewed by Cursor Bugbot
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| decimals={ token.decimals ?? '0' } | ||
| loading={ isLoading } | ||
| /> | ||
| ) } |
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.
Holder percentage computed from confidential encrypted balance
High Severity
For ERC-7984 tokens, the "Quantity" column correctly renders ConfidentialValue (encrypted placeholder), but the "Percentage" section still computes BigNumber(holder.value).div(BigNumber(token.total_supply)). Since holder.value is confidential/encrypted for ERC-7984, this calculation will produce NaN or nonsensical results. The condition token.total_supply && token.type !== 'ERC-404' needs to also exclude 'ERC-7984' in both TokenHoldersTableItem and TokenHoldersListItem.
Additional Locations (1)
| type TokenGroup = [string, TokenSelectDataItem]; | ||
|
|
||
| const NFT_TOKEN_GROUPS_ORDER = [ 'ERC-721', 'ERC-1155', 'ERC-404' ] as const; | ||
| const NFT_TOKEN_GROUPS_ORDER = [ 'ERC-721', 'ERC-1155', 'ERC-404', 'ERC-7984' ] as const; |
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.
ERC-7984 misplaced in NFT token groups constant
Low Severity
ERC-7984 is a confidential fungible token (akin to ERC-20), but it's been added to NFT_TOKEN_GROUPS_ORDER alongside ERC-721, ERC-1155, and ERC-404. While the sort order works correctly, this naming is misleading — the constant's name implies it contains only NFT types, which makes future maintenance confusing.
| flexGrow={ 1 } | ||
| /> | ||
| </Flex> | ||
| ) } |
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.
Duplicate value rows rendered for ERC-7984 transfers
Medium Severity
The ERC-7984 ConfidentialValue block at line 91 renders unconditionally for ERC-7984 tokens (token && token.type === 'ERC-7984'), while the existing AssetValue block at line 67 also matches ERC-7984 because hasTokenTransferValue returns true for it and doesn't check total.value !== null. Both blocks render simultaneously, producing duplicate "Value" rows. The shared version in ui/shared/TokenTransfer/TokenTransferListItem.tsx correctly uses mutually exclusive conditions (total.value !== null vs !total || total.value === null).
Additional Locations (1)
| } | | ||
| { | ||
| token: TokenInfo | null; | ||
| total: Erc20TotalPayload | null; |
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 object is already part of the union. Is this change intentional?
| const erc7984Query = useQueryWithPages({ | ||
| resourceName: 'general:address_tokens', | ||
| pathParams: { hash }, | ||
| filters: { type: 'ERC-7984' }, | ||
| scrollRef, | ||
| options: { | ||
| enabled: isQueryEnabled && tab === 'tokens_erc7984', | ||
| refetchOnMount: false, | ||
| placeholderData: generateListStub<'general:address_tokens'>(ADDRESS_TOKEN_BALANCE_ERC_20, 10, { next_page_params: null }), | ||
| }, | ||
| }); | ||
|
|
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 believe we can add this token type to erc20Query without needing to create a separate tab in the UI. The table structure for these token types is similar.
| tokensQuery: QueryWithPagesResult<'general:address_tokens'>; | ||
| }; | ||
|
|
||
| const ERC7984Tokens = ({ tokensQuery }: Props) => { |
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 assume we can re-use the component for ERC20 tokens here.
| <Skeleton loading={ loading } display="inline-block"> | ||
| ••••• | ||
| </Skeleton> |
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.
| <Skeleton loading={ loading } display="inline-block"> | |
| ••••• | |
| </Skeleton> | |
| <ConfidentialValue loading={ loading }> |
| <ConfidentialValue loading={ false } wordBreak="break-word"/> | ||
| <TokenEntity | ||
| token={{ ...data.token, name: data.token.symbol || data.token.name }} | ||
| noCopy | ||
| noSymbol | ||
| w="auto" | ||
| /> |
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.
| <ConfidentialValue loading={ false } wordBreak="break-word"/> | |
| <TokenEntity | |
| token={{ ...data.token, name: data.token.symbol || data.token.name }} | |
| noCopy | |
| noSymbol | |
| w="auto" | |
| /> | |
| <ConfidentialTokenValue .../> |
| alignItems={ layout === 'vertical' ? 'flex-end' : 'center' } | ||
| { ...rest } | ||
| > | ||
| <Flex alignItems="center"> |
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 believe this wrapper is not needed.
| <TokenValue | ||
| amount={ item.total.value } | ||
| token={ item.token } | ||
| decimals={ item.total.decimals || '0' } | ||
| loading={ isLoading } | ||
| /> |
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.
| { isErc20 ? <ConfidentialTokenValue ... /> : <TokenValue .../> |
|
|
||
| export const TOKEN_TYPES: Record<string, string> = { | ||
| 'ERC-20': `${ tokenStandardName }-20`, | ||
| 'ERC-7984': `${ tokenStandardName }-7984`, |
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.
As we discussed internally, we would like this token type to appear only in certain instances or chains. Therefore, let's remove the hard-coded value and pass it as an additional token type via the NEXT_PUBLIC_NETWORK_ADDITIONAL_TOKEN_TYPES run-time environment variable.


Description and Related Issue(s)
This PR integrates ERC-7984 confidential tokens introduced for backend in blockscout/blockscout#13593 .
One main difference between ERC-20 and ERC-7984 is that token balances are not known to public (because of their encrypted nature), that's why we show "•••••" placeholder instead of the actual value (in future improvements confidential protocol integrations, these values might be decrypted with the wallet having a decryption access).
Proposed Changes
A new type of token, ERC-7984, which mostly works as ERC-20 excluding encrypted balances, which was described earlier.
Additional Information
ERC-7984 readings:
Note
Medium Risk
Touches many token/transfer UI surfaces and realtime socket update wiring; while mostly additive, regressions could affect token balances/transfers rendering and pagination/socket refresh behavior.
Overview
Adds ERC-7984 (confidential token) as a first-class token type, including socket event typing (
updated_token_balances_erc_7984) and token-type helpers so ERC-7984 participates in token-type labels and transfer-value handling.Extends the Address Tokens UI with a dedicated
${tokenStandard}-7984tab and new list/table components, wires ERC-7984 into token fetching + socket updates, and updates token selectors/grouping/sorting to include the new type.Updates multiple transfer/holders views (token transfers tables/lists/snippets, advanced filter amount column, token holders) to render masked placeholders via new
ConfidentialValue/ConfidentialTokenValuecomponents when ERC-7984 amounts are unavailable, and adds a new quick-search category for confidential tokens.Written by Cursor Bugbot for commit 8ea5a5b. This will update automatically on new commits. Configure here.