1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

use safer toChecksum utility (#11117)

This commit is contained in:
Brad Decker 2021-05-17 16:19:39 -05:00 committed by GitHub
parent 9386e3cb03
commit d9a2165f69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 94 additions and 91 deletions

View File

@ -1,8 +1,8 @@
import punycode from 'punycode/punycode';
import { toChecksumAddress } from 'ethereumjs-util';
import { ObservableStore } from '@metamask/obs-store';
import log from 'loglevel';
import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../shared/constants/network';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import Ens from './ens';
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
@ -43,7 +43,7 @@ export default class EnsController {
}
reverseResolveAddress(address) {
return this._reverseResolveAddress(toChecksumAddress(address));
return this._reverseResolveAddress(toChecksumHexAddress(address));
}
async _reverseResolveAddress(address) {
@ -79,7 +79,7 @@ export default class EnsController {
return undefined;
}
if (toChecksumAddress(registeredAddress) !== address) {
if (toChecksumHexAddress(registeredAddress) !== address) {
return undefined;
}

View File

@ -1,8 +1,8 @@
import { ObservableStore } from '@metamask/obs-store';
import log from 'loglevel';
import { normalize as normalizeAddress } from 'eth-sig-util';
import { toChecksumAddress } from 'ethereumjs-util';
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
const fetchWithTimeout = getFetchWithTimeout(30000);
@ -45,7 +45,7 @@ export default class TokenRatesController {
this._tokens.forEach((token) => {
const price =
prices[token.address.toLowerCase()] ||
prices[toChecksumAddress(token.address)];
prices[toChecksumHexAddress(token.address)];
contractExchangeRates[normalizeAddress(token.address)] = price
? price[nativeCurrency]
: 0;

View File

@ -10,7 +10,7 @@ import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager'
import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware';
import KeyringController from 'eth-keyring-controller';
import { Mutex } from 'await-semaphore';
import { toChecksumAddress, stripHexPrefix } from 'ethereumjs-util';
import { stripHexPrefix } from 'ethereumjs-util';
import log from 'loglevel';
import TrezorKeyring from 'eth-trezor-keyring';
import LedgerBridgeKeyring from '@metamask/eth-ledger-bridge-keyring';
@ -27,6 +27,7 @@ import {
import { TRANSACTION_STATUSES } from '../../shared/constants/transaction';
import { MAINNET_CHAIN_ID } from '../../shared/constants/network';
import { UI_NOTIFICATIONS } from '../../shared/notifications';
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
import ComposableObservableStore from './lib/ComposableObservableStore';
import AccountTracker from './lib/account-tracker';
@ -1123,14 +1124,14 @@ export default class MetamaskController extends EventEmitter {
// Filter ERC20 tokens
const filteredAccountTokens = {};
Object.keys(accountTokens).forEach((address) => {
const checksummedAddress = toChecksumAddress(address);
const checksummedAddress = toChecksumHexAddress(address);
filteredAccountTokens[checksummedAddress] = {};
Object.keys(accountTokens[address]).forEach((chainId) => {
filteredAccountTokens[checksummedAddress][chainId] =
chainId === MAINNET_CHAIN_ID
? accountTokens[address][chainId].filter(
({ address: tokenAddress }) => {
const checksumAddress = toChecksumAddress(tokenAddress);
const checksumAddress = toChecksumHexAddress(tokenAddress);
return contractMap[checksumAddress]
? contractMap[checksumAddress].erc20
: true;
@ -1167,10 +1168,10 @@ export default class MetamaskController extends EventEmitter {
const accounts = {
hd: hdAccounts
.filter((item, pos) => hdAccounts.indexOf(item) === pos)
.map((address) => toChecksumAddress(address)),
.map((address) => toChecksumHexAddress(address)),
simpleKeyPair: simpleKeyPairAccounts
.filter((item, pos) => simpleKeyPairAccounts.indexOf(item) === pos)
.map((address) => toChecksumAddress(address)),
.map((address) => toChecksumHexAddress(address)),
ledger: [],
trezor: [],
};
@ -1180,7 +1181,7 @@ export default class MetamaskController extends EventEmitter {
let { transactions } = this.txController.store.getState();
// delete tx for other accounts that we're not importing
transactions = Object.values(transactions).filter((tx) => {
const checksummedTxFrom = toChecksumAddress(tx.txParams.from);
const checksummedTxFrom = toChecksumHexAddress(tx.txParams.from);
return accounts.hd.includes(checksummedTxFrom);
});

View File

@ -1,5 +1,5 @@
import { cloneDeep } from 'lodash';
import { toChecksumAddress } from 'ethereumjs-util';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
const version = 39;
@ -12,7 +12,7 @@ function isOldDai(token = {}) {
token &&
typeof token === 'object' &&
token.symbol === DAI_V1_TOKEN_SYMBOL &&
toChecksumAddress(token.address) === DAI_V1_CONTRACT_ADDRESS
toChecksumHexAddress(token.address) === DAI_V1_CONTRACT_ADDRESS
);
}

View File

@ -3,6 +3,7 @@ import {
isValidAddress,
isValidChecksumAddress,
addHexPrefix,
toChecksumAddress,
} from 'ethereumjs-util';
export const BURN_ADDRESS = '0x0000000000000000000000000000000000000000';
@ -51,3 +52,22 @@ export function isValidHexAddress(
return isValidAddress(addressToCheck);
}
export function toChecksumHexAddress(address) {
if (!address) {
// our internal checksumAddress function that this method replaces would
// return an empty string for nullish input. If any direct usages of
// ethereumjs-util.toChecksumAddress were called with nullish input it
// would have resulted in an error on version 5.1.
return '';
}
const hexPrefixed = addHexPrefix(address);
if (!isHexString(hexPrefixed)) {
// Version 5.1 of ethereumjs-utils would have returned '0xY' for input 'y'
// but we shouldn't waste effort trying to change case on a clearly invalid
// string. Instead just return the hex prefixed original string which most
// closely mimics the original behavior.
return hexPrefixed;
}
return toChecksumAddress(addHexPrefix(address));
}

View File

@ -1,18 +1,19 @@
import React from 'react';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import * as utils from '../../../helpers/utils/util';
import Identicon from '../../ui/identicon';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import AccountListItem from './account-list-item';
jest.mock('../../../../shared/modules/hexstring-utils', () => ({
toChecksumHexAddress: jest.fn(() => 'mockCheckSumAddress'),
}));
describe('AccountListItem Component', () => {
let wrapper, propsMethodSpies, checksumAddressStub;
let wrapper, propsMethodSpies;
describe('render', () => {
beforeAll(() => {
checksumAddressStub = sinon
.stub(utils, 'checksumAddress')
.returns('mockCheckSumAddress');
propsMethodSpies = {
handleClick: sinon.spy(),
};
@ -36,7 +37,6 @@ describe('AccountListItem Component', () => {
afterEach(() => {
propsMethodSpies.handleClick.resetHistory();
checksumAddressStub.resetHistory();
});
afterAll(() => {
@ -126,9 +126,7 @@ describe('AccountListItem Component', () => {
expect(
wrapper.find('.account-list-item__account-address').text(),
).toStrictEqual('mockCheckSumAddress');
expect(checksumAddressStub.getCall(0).args).toStrictEqual([
'mockAddress',
]);
expect(toChecksumHexAddress).toHaveBeenCalledWith('mockAddress');
});
it('should not render the account address as a checksumAddress if displayAddress is false', () => {

View File

@ -1,8 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { checksumAddress } from '../../../helpers/utils/util';
import Identicon from '../../ui/identicon';
import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
export default function AccountListItem({
account,
@ -34,7 +34,7 @@ export default function AccountListItem({
{displayAddress && name && (
<div className="account-list-item__account-address">
{checksumAddress(address)}
{toChecksumHexAddress(address)}
</div>
)}
</div>

View File

@ -4,10 +4,10 @@ import React, { Component } from 'react';
import { stripHexPrefix } from 'ethereumjs-util';
import copyToClipboard from 'copy-to-clipboard';
import { checksumAddress } from '../../../../helpers/utils/util';
import ReadOnlyInput from '../../../ui/readonly-input';
import Button from '../../../ui/button';
import AccountModalContainer from '../account-modal-container';
import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils';
export default class ExportPrivateKeyModal extends Component {
static contextTypes = {
@ -149,7 +149,7 @@ export default class ExportPrivateKeyModal extends Component {
<span className="export-private-key-modal__account-name">{name}</span>
<ReadOnlyInput
wrapperClass="ellip-address-wrapper"
value={checksumAddress(address)}
value={toChecksumHexAddress(address)}
/>
<div className="export-private-key-modal__divider" />
<span className="export-private-key-modal__body-title">

View File

@ -1,9 +1,10 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import copyToClipboard from 'copy-to-clipboard';
import { shortenAddress, checksumAddress } from '../../../helpers/utils/util';
import { shortenAddress } from '../../../helpers/utils/util';
import Tooltip from '../../ui/tooltip';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
class SelectedAccount extends Component {
state = {
@ -32,7 +33,7 @@ class SelectedAccount extends Component {
render() {
const { t } = this.context;
const { selectedIdentity } = this.props;
const checksummedAddress = checksumAddress(selectedIdentity.address);
const checksummedAddress = toChecksumHexAddress(selectedIdentity.address);
return (
<div className="selected-account">

View File

@ -1,10 +1,10 @@
import { connect } from 'react-redux';
import { checksumAddress } from '../../../helpers/utils/util';
import { tryReverseResolveAddress } from '../../../store/actions';
import {
getAddressBook,
getRpcPrefsForCurrentProvider,
} from '../../../selectors';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import TransactionListItemDetails from './transaction-list-item-details.component';
const mapStateToProps = (state, ownProps) => {
@ -13,7 +13,7 @@ const mapStateToProps = (state, ownProps) => {
const { recipientAddress, senderAddress } = ownProps;
let recipientEns;
if (recipientAddress) {
const address = checksumAddress(recipientAddress);
const address = toChecksumHexAddress(recipientAddress);
recipientEns = ensResolutionsByAddress[address] || '';
}
const addressBook = getAddressBook(state);

View File

@ -2,9 +2,8 @@ import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import contractMap from '@metamask/contract-metadata';
import { isHexString, addHexPrefix } from 'ethereumjs-util';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import { checksumAddress } from '../../../helpers/utils/util';
import Jazzicon from '../jazzicon';
import BlockieIdenticon from './blockieIdenticon';
@ -86,11 +85,9 @@ export default class Identicon extends PureComponent {
}
if (address) {
const checksummedAddress =
isHexString(addHexPrefix(address)) &&
checksumAddress(addHexPrefix(address));
const checksummedAddress = toChecksumHexAddress(address);
if (contractMap[checksummedAddress]?.logo) {
if (checksummedAddress && contractMap[checksummedAddress]?.logo) {
return this.renderJazzicon();
}

View File

@ -4,7 +4,7 @@ import qrCode from 'qrcode-generator';
import { connect } from 'react-redux';
import { isHexPrefixed } from 'ethereumjs-util';
import ReadOnlyInput from '../readonly-input/readonly-input';
import { checksumAddress } from '../../../helpers/utils/util';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
export default connect(mapStateToProps)(QrCodeView);
@ -20,9 +20,9 @@ function mapStateToProps(state) {
function QrCodeView(props) {
const { Qr, warning } = props;
const { message, data } = Qr;
const address = `${isHexPrefixed(data) ? 'ethereum:' : ''}${checksumAddress(
data,
)}`;
const address = `${
isHexPrefixed(data) ? 'ethereum:' : ''
}${toChecksumHexAddress(data)}`;
const qrImage = qrCode(4, 'M');
qrImage.addData(address);
qrImage.make();
@ -50,7 +50,7 @@ function QrCodeView(props) {
<ReadOnlyInput
wrapperClass="ellip-address-wrapper"
autoFocus
value={checksumAddress(data)}
value={toChecksumHexAddress(data)}
/>
</div>
);

View File

@ -4,9 +4,10 @@ import classnames from 'classnames';
import copyToClipboard from 'copy-to-clipboard';
import Tooltip from '../tooltip';
import Identicon from '../identicon';
import { checksumAddress, shortenAddress } from '../../../helpers/utils/util';
import { shortenAddress } from '../../../helpers/utils/util';
import AccountMismatchWarning from '../account-mismatch-warning/account-mismatch-warning.component';
import { useI18nContext } from '../../../hooks/useI18nContext';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import {
DEFAULT_VARIANT,
CARDS_VARIANT,
@ -56,7 +57,10 @@ function SenderAddress({
>
{!addressOnly && (
<div className="sender-to-recipient__sender-icon">
<Identicon address={checksumAddress(senderAddress)} diameter={24} />
<Identicon
address={toChecksumHexAddress(senderAddress)}
diameter={24}
/>
</div>
)}
<Tooltip
@ -203,8 +207,8 @@ export default function SenderToRecipient({
warnUserOnAccountMismatch,
}) {
const t = useI18nContext();
const checksummedSenderAddress = checksumAddress(senderAddress);
const checksummedRecipientAddress = checksumAddress(recipientAddress);
const checksummedSenderAddress = toChecksumHexAddress(senderAddress);
const checksummedRecipientAddress = toChecksumHexAddress(recipientAddress);
return (
<div className={classnames('sender-to-recipient', variantHash[variant])}>

View File

@ -1,7 +1,8 @@
import contractMap from '@metamask/contract-metadata';
import { isHexString, addHexPrefix } from 'ethereumjs-util';
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
import { checksumAddress } from './util';
import {
isValidHexAddress,
toChecksumHexAddress,
} from '../../../shared/modules/hexstring-utils';
let iconFactory;
@ -18,11 +19,7 @@ function IconFactory(jazzicon) {
}
IconFactory.prototype.iconForAddress = function (address, diameter) {
let addr = address;
if (isHexString(addHexPrefix(address))) {
addr = checksumAddress(addHexPrefix(address));
}
const addr = toChecksumHexAddress(address);
if (iconExistsFor(addr)) {
return imageElFor(addr);

View File

@ -12,6 +12,7 @@ import {
RINKEBY_CHAIN_ID,
ROPSTEN_CHAIN_ID,
} from '../../../shared/constants/network';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
// formatData :: ( date: <Unix Timestamp> ) -> String
export function formatDate(date, format = "M/d/y 'at' T") {
@ -67,7 +68,7 @@ export function addressSummary(
if (!address) {
return '';
}
let checked = checksumAddress(address);
let checked = toChecksumHexAddress(address);
if (!includeHex) {
checked = ethUtil.stripHexPrefix(checked);
}
@ -195,18 +196,6 @@ export function exportAsFile(filename, data, type = 'text/csv') {
}
}
/**
* Safely checksumms a potentially-null address
*
* @param {string} [address] - address to checksum
* @returns {string} checksummed address
*
*/
export function checksumAddress(address) {
const checksummed = address ? ethUtil.toChecksumAddress(address) : '';
return checksummed;
}
/**
* Shortens an Ethereum address for display, preserving the beginning and end.
* Returns the given address if it is no longer than 10 characters.

View File

@ -3,7 +3,6 @@ import { useSelector } from 'react-redux';
import contractMap from '@metamask/contract-metadata';
import BigNumber from 'bignumber.js';
import { isEqual, shuffle } from 'lodash';
import { checksumAddress } from '../helpers/utils/util';
import { getTokenFiatAmount } from '../helpers/utils/token-util';
import {
getTokenExchangeRates,
@ -14,6 +13,7 @@ import {
} from '../selectors';
import { getSwapsTokens } from '../ducks/swaps/swaps';
import { isSwapsDefaultTokenSymbol } from '../../shared/modules/swaps.utils';
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
import { useEqualityCheck } from './useEqualityCheck';
const tokenList = shuffle(
@ -58,12 +58,12 @@ export function getRenderableTokenData(
) || '';
const usedIconUrl =
iconUrl ||
(contractMap[checksumAddress(address)] &&
`images/contract/${contractMap[checksumAddress(address)].logo}`);
(contractMap[toChecksumHexAddress(address)] &&
`images/contract/${contractMap[toChecksumHexAddress(address)].logo}`);
return {
...token,
primaryLabel: symbol,
secondaryLabel: name || contractMap[checksumAddress(address)]?.name,
secondaryLabel: name || contractMap[toChecksumHexAddress(address)]?.name,
rightPrimaryLabel:
string && `${new BigNumber(string).round(6).toString()} ${symbol}`,
rightSecondaryLabel: formattedFiat,
@ -71,7 +71,7 @@ export function getRenderableTokenData(
identiconAddress: usedIconUrl ? null : address,
balance,
decimals,
name: name || contractMap[checksumAddress(address)]?.name,
name: name || contractMap[toChecksumHexAddress(address)]?.name,
rawFiat,
};
}

View File

@ -24,11 +24,7 @@ import { getHexGasTotal } from '../../helpers/utils/confirm-tx.util';
import { isBalanceSufficient, calcGasTotal } from '../send/send.utils';
import { conversionGreaterThan } from '../../helpers/utils/conversion-util';
import { MIN_GAS_LIMIT_DEC } from '../send/send.constants';
import {
checksumAddress,
shortenAddress,
valuesFor,
} from '../../helpers/utils/util';
import { shortenAddress, valuesFor } from '../../helpers/utils/util';
import {
getAdvancedInlineGasShown,
getCustomNonceValue,
@ -43,6 +39,7 @@ import {
} from '../../selectors';
import { getMostRecentOverviewPage } from '../../ducks/history/history';
import { transactionMatchesNetwork } from '../../../shared/modules/transaction.utils';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
import ConfirmTransactionBase from './confirm-transaction-base.component';
const casedContractMap = Object.keys(contractMap).reduce((acc, base) => {
@ -107,9 +104,9 @@ const mapStateToProps = (state, ownProps) => {
const toName =
identities[toAddress]?.name ||
casedContractMap[toAddress]?.name ||
shortenAddress(checksumAddress(toAddress));
shortenAddress(toChecksumHexAddress(toAddress));
const checksummedAddress = checksumAddress(toAddress);
const checksummedAddress = toChecksumHexAddress(toAddress);
const addressBookObject = addressBook[checksummedAddress];
const toEns = ensResolutionsByAddress[checksummedAddress] || '';
const toNickname = addressBookObject ? addressBookObject.name : '';

View File

@ -1,4 +1,3 @@
import { toChecksumAddress } from 'ethereumjs-util';
import contractMap from '@metamask/contract-metadata';
import { isConfusing } from 'unicode-confusables';
import {
@ -19,6 +18,7 @@ import {
import {
isBurnAddress,
isValidHexAddress,
toChecksumHexAddress,
} from '../../../../../shared/modules/hexstring-utils';
export function getToErrorObject(to, sendTokenAddress, chainId) {
@ -44,7 +44,8 @@ export function getToWarningObject(to, tokens = [], sendToken = null) {
let toWarning = null;
if (
sendToken &&
(toChecksumAddress(to) in contractMap || checkExistingAddresses(to, tokens))
(toChecksumHexAddress(to) in contractMap ||
checkExistingAddresses(to, tokens))
) {
toWarning = KNOWN_RECIPIENT_ADDRESS_ERROR;
} else if (isValidDomainName(to) && isConfusing(to)) {

View File

@ -22,6 +22,7 @@ jest.mock('../../../../../shared/modules/hexstring-utils', () => ({
Boolean(to.match(/^[0xabcdef123456798]+$/u)),
),
isBurnAddress: jest.fn(() => false),
toChecksumHexAddress: jest.fn((input) => input),
}));
describe('add-recipient utils', () => {

View File

@ -2,11 +2,11 @@ import { compose } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
import { getAddressBookEntry } from '../../../../selectors';
import { checksumAddress } from '../../../../helpers/utils/util';
import {
CONTACT_EDIT_ROUTE,
CONTACT_LIST_ROUTE,
} from '../../../../helpers/constants/routes';
import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils';
import ViewContact from './view-contact.component';
const mapStateToProps = (state, ownProps) => {
@ -25,7 +25,7 @@ const mapStateToProps = (state, ownProps) => {
return {
name,
address: contact ? address : null,
checkSummedAddress: checksumAddress(address),
checkSummedAddress: toChecksumHexAddress(address),
memo,
editRoute: CONTACT_EDIT_ROUTE,
listRoute: CONTACT_LIST_ROUTE,

View File

@ -14,11 +14,7 @@ import {
ALLOWED_SWAPS_CHAIN_IDS,
} from '../../shared/constants/swaps';
import {
shortenAddress,
checksumAddress,
getAccountByAddress,
} from '../helpers/utils/util';
import { shortenAddress, getAccountByAddress } from '../helpers/utils/util';
import {
getValueFromWeiHex,
hexToDecimal,
@ -26,6 +22,7 @@ import {
import { TEMPLATED_CONFIRMATION_MESSAGE_TYPES } from '../pages/confirmation/templates';
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
import { getNativeCurrency } from './send';
/**
@ -262,7 +259,7 @@ export function getAddressBook(state) {
export function getAddressBookEntry(state, address) {
const addressBook = getAddressBook(state);
const entry = addressBook.find(
(contact) => contact.address === checksumAddress(address),
(contact) => contact.address === toChecksumHexAddress(address),
);
return entry;
}

View File

@ -3,7 +3,6 @@ import pify from 'pify';
import log from 'loglevel';
import { capitalize } from 'lodash';
import getBuyEthUrl from '../../app/scripts/lib/buy-eth-url';
import { checksumAddress } from '../helpers/utils/util';
import { calcTokenBalance, estimateGasForSend } from '../pages/send/send.utils';
import {
fetchLocale,
@ -24,6 +23,7 @@ import {
import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account';
import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask';
import { LISTED_CONTRACT_ADDRESSES } from '../../shared/constants/tokens';
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
import * as actionConstants from './actionConstants';
let background = null;
@ -1717,7 +1717,7 @@ export function addToAddressBook(recipient, nickname = '', memo = '') {
let set;
try {
set = await promisifiedBackground.setAddressBook(
checksumAddress(recipient),
toChecksumHexAddress(recipient),
nickname,
chainId,
memo,
@ -1743,7 +1743,7 @@ export function removeFromAddressBook(chainId, addressToRemove) {
return async () => {
await promisifiedBackground.removeFromAddressBook(
chainId,
checksumAddress(addressToRemove),
toChecksumHexAddress(addressToRemove),
);
};
}