From 26926f47fb16578091a7a31b9de23be59c3af890 Mon Sep 17 00:00:00 2001 From: tom Date: Thu, 28 Mar 2024 18:08:55 +0100 Subject: [PATCH 1/3] Numbers over 16(?) digits are rounded in contract method fields Fixes #1750 --- .../contract/methodForm/useArgTypeMatchInt.tsx | 4 ++-- .../contract/methodForm/useFormatFieldValue.tsx | 5 ++++- .../contract/methodForm/useValidateField.tsx | 14 +++++++++++--- ui/address/contract/methodForm/utils.ts | 8 ++++---- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/ui/address/contract/methodForm/useArgTypeMatchInt.tsx b/ui/address/contract/methodForm/useArgTypeMatchInt.tsx index bb3f375e7c..fa6b994021 100644 --- a/ui/address/contract/methodForm/useArgTypeMatchInt.tsx +++ b/ui/address/contract/methodForm/useArgTypeMatchInt.tsx @@ -9,8 +9,8 @@ interface Params { export interface MatchInt { isUnsigned: boolean; power: string; - min: number; - max: number; + min: bigint; + max: bigint; } export default function useArgTypeMatchInt({ argType }: Params): MatchInt | null { diff --git a/ui/address/contract/methodForm/useFormatFieldValue.tsx b/ui/address/contract/methodForm/useFormatFieldValue.tsx index aec859f5f6..6c82c682b3 100644 --- a/ui/address/contract/methodForm/useFormatFieldValue.tsx +++ b/ui/address/contract/methodForm/useFormatFieldValue.tsx @@ -17,8 +17,11 @@ export default function useFormatFieldValue({ argType, argTypeMatchInt }: Params } if (argTypeMatchInt) { + // we have to store all numbers as strings to avoid precision loss + // and we cannot store them as BigInt because the NumberFormat component will not work properly + // so we just remove all white spaces here otherwise the `viem` library will throw an error on attempt to write value to a contract const formattedString = value.replace(/\s/g, ''); - return parseInt(formattedString); + return formattedString; } if (argType === 'bool') { diff --git a/ui/address/contract/methodForm/useValidateField.tsx b/ui/address/contract/methodForm/useValidateField.tsx index e0766efcc2..5151cffcba 100644 --- a/ui/address/contract/methodForm/useValidateField.tsx +++ b/ui/address/contract/methodForm/useValidateField.tsx @@ -20,7 +20,7 @@ export default function useValidateField({ isOptional, argType, argTypeMatchInt // some values are formatted before they are sent to the validator // see ./useFormatFieldValue.tsx hook - return React.useCallback((value: string | number | boolean | undefined) => { + return React.useCallback((value: string | boolean | undefined) => { if (value === undefined || value === '') { return isOptional ? true : 'Field is required'; } @@ -41,11 +41,19 @@ export default function useValidateField({ isOptional, argType, argTypeMatchInt } if (argTypeMatchInt) { - if (typeof value !== 'number' || Object.is(value, NaN)) { + const valueBi = (() => { + try { + return BigInt(value); + } catch (error) { + return null; + } + })(); + + if (typeof value !== 'string' || valueBi === null) { return 'Invalid integer format'; } - if (value > argTypeMatchInt.max || value < argTypeMatchInt.min) { + if (valueBi > argTypeMatchInt.max || valueBi < argTypeMatchInt.min) { const lowerBoundary = argTypeMatchInt.isUnsigned ? '0' : `-1 * 2 ^ ${ Number(argTypeMatchInt.power) - 1 }`; const upperBoundary = argTypeMatchInt.isUnsigned ? `2 ^ ${ argTypeMatchInt.power } - 1` : `2 ^ ${ Number(argTypeMatchInt.power) - 1 } - 1`; return `Value should be in range from "${ lowerBoundary }" to "${ upperBoundary }" inclusively`; diff --git a/ui/address/contract/methodForm/utils.ts b/ui/address/contract/methodForm/utils.ts index 3b6fe2953f..61515577d3 100644 --- a/ui/address/contract/methodForm/utils.ts +++ b/ui/address/contract/methodForm/utils.ts @@ -2,7 +2,7 @@ import _set from 'lodash/set'; import type { SmartContractMethodInput } from 'types/api/contract'; -export type ContractMethodFormFields = Record; +export type ContractMethodFormFields = Record; export const INT_REGEXP = /^(u)?int(\d+)?$/i; @@ -11,9 +11,9 @@ export const BYTES_REGEXP = /^bytes(\d+)?$/i; export const ARRAY_REGEXP = /^(.*)\[(\d*)\]$/; export const getIntBoundaries = (power: number, isUnsigned: boolean) => { - const maxUnsigned = 2 ** power; - const max = isUnsigned ? maxUnsigned - 1 : maxUnsigned / 2 - 1; - const min = isUnsigned ? 0 : -maxUnsigned / 2; + const maxUnsigned = BigInt(2 ** power); + const max = isUnsigned ? maxUnsigned - BigInt(1) : maxUnsigned / BigInt(2) - BigInt(1); + const min = isUnsigned ? BigInt(0) : -maxUnsigned / BigInt(2); return [ min, max ]; }; From f0b19b63b0781ffc0cc7a89bdff6a69103059708 Mon Sep 17 00:00:00 2001 From: Yan Vaskov <72267126+yvaskov@users.noreply.github.com> Date: Mon, 1 Apr 2024 13:47:21 +0400 Subject: [PATCH 2/3] Update values.yaml.gotmpl Changed public rpc to Sepolia --- deploy/values/review/values.yaml.gotmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/values/review/values.yaml.gotmpl b/deploy/values/review/values.yaml.gotmpl index b2ef806295..3d0224acd2 100644 --- a/deploy/values/review/values.yaml.gotmpl +++ b/deploy/values/review/values.yaml.gotmpl @@ -4,7 +4,7 @@ imagePullSecrets: - name: regcred config: network: - id: 5 + id: 11155111 name: Blockscout shortname: Blockscout currency: @@ -65,7 +65,7 @@ frontend: NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM: https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form NEXT_PUBLIC_LOGOUT_URL: https://blockscoutcom.us.auth0.com/v2/logout NEXT_PUBLIC_HOMEPAGE_CHARTS: "['daily_txs','coin_price','market_cap']" - NEXT_PUBLIC_NETWORK_RPC_URL: https://rpc.ankr.com/eth_goerli + NEXT_PUBLIC_NETWORK_RPC_URL: https://eth-sepolia.public.blastapi.io NEXT_PUBLIC_NETWORK_EXPLORERS: "[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/etherscan.png?raw=true','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]" NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace-categories/default.json NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d From 989aeb68612f27b07e5d5cd7eee65d429ed036d0 Mon Sep 17 00:00:00 2001 From: Yan Vaskov <72267126+yvaskov@users.noreply.github.com> Date: Mon, 1 Apr 2024 14:46:21 +0400 Subject: [PATCH 3/3] Set NEXT_PUBLIC_NETWORK_ID --- deploy/values/review/values.yaml.gotmpl | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/values/review/values.yaml.gotmpl b/deploy/values/review/values.yaml.gotmpl index 3d0224acd2..f8098bae40 100644 --- a/deploy/values/review/values.yaml.gotmpl +++ b/deploy/values/review/values.yaml.gotmpl @@ -66,6 +66,7 @@ frontend: NEXT_PUBLIC_LOGOUT_URL: https://blockscoutcom.us.auth0.com/v2/logout NEXT_PUBLIC_HOMEPAGE_CHARTS: "['daily_txs','coin_price','market_cap']" NEXT_PUBLIC_NETWORK_RPC_URL: https://eth-sepolia.public.blastapi.io + NEXT_PUBLIC_NETWORK_ID: '11155111' NEXT_PUBLIC_NETWORK_EXPLORERS: "[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','logo':'https://github.com/blockscout/frontend-configs/blob/main/configs/explorer-logos/etherscan.png?raw=true','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]" NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/marketplace-categories/default.json NEXT_PUBLIC_GRAPHIQL_TRANSACTION: 0xf7d4972356e6ae44ae948d0cf19ef2beaf0e574c180997e969a2837da15e349d