Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ function unclaimedFeesStub(token0Amount: bigint, token1Amount: bigint) {
address: "0x1234567890123456789012345678901234567890",
amount: token0Amount,
symbol: "FOO",
decimals: 18,
},
token1: {
address: "0x0987654321098765432109876543210987654321",
amount: token1Amount,
symbol: "BAR",
decimals: 18,
},
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ export function ClaimRewardsPage(props: {
address: string;
amount: bigint;
symbol: string;
decimals: number;
};
token1: {
address: string;
amount: bigint;
symbol: string;
decimals: number;
};
};
chainSlug: string;
Expand Down Expand Up @@ -98,11 +100,13 @@ export function ClaimRewardsPageUI(props: {
address: string;
amount: bigint;
symbol: string;
decimals: number;
};
token1: {
address: string;
amount: bigint;
symbol: string;
decimals: number;
};
};
recipient: string;
Expand Down Expand Up @@ -275,6 +279,7 @@ function TokenReward(props: {
address: string;
amount: bigint;
symbol: string;
decimals: number;
};
client: ThirdwebClient;
chain: Chain;
Expand Down Expand Up @@ -303,7 +308,8 @@ function TokenReward(props: {
</div>
<div className="space-y-0.5">
<p className="font-bold text-sm">
{toTokens(props.token.amount, 18)} {props.token.symbol}
{toTokens(props.token.amount, props.token.decimals)}{" "}
{props.token.symbol}
</p>
<Link
target="_blank"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default async function Page(props: {
const chain = info.clientContract.chain;
const assetContractServer = info.serverContract;
const serverClient = assetContractServer.client;
const chainMetadata = info.chainMetadata;

const { address: entrypointContractAddress } =
await getDeployedEntrypointERC20({
Expand All @@ -56,6 +57,7 @@ export default async function Page(props: {

// Note: must use server contract/client here
const unclaimedFees = await getUnclaimedFees({
chainMetadata,
positionManager: getContract({
address: reward.positionManager,
chain,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { ThirdwebContract } from "thirdweb";
import { getContract, readContract } from "thirdweb";
import { getAddress, getContract, readContract, ZERO_ADDRESS } from "thirdweb";
import type { ChainMetadata } from "thirdweb/chains";
import { symbol } from "thirdweb/extensions/common";
import { decimals } from "thirdweb/extensions/erc20";

const maxUint128 = 2n ** 128n - 1n;

export async function getUnclaimedFees(params: {
positionManager: ThirdwebContract;
chainMetadata: ChainMetadata;
reward: {
tokenId: bigint;
recipient: string;
Expand Down Expand Up @@ -56,33 +59,60 @@ export async function getUnclaimedFees(params: {
const token0Address = positionsResult[2];
const token1Address = positionsResult[3];

const [token0Symbol, token1Symbol] = await Promise.all([
symbol({
contract: getContract({
address: token0Address,
chain,
client,
}),
}),
symbol({
contract: getContract({
address: token1Address,
chain,
client,
}),
}),
]);
const token0Contract = getContract({
address: token0Address,
chain,
client,
});

const token1Contract = getContract({
address: token1Address,
chain,
client,
});

const isToken0Native = getAddress(token0Address) === getAddress(ZERO_ADDRESS);
const isToken1Native = getAddress(token1Address) === getAddress(ZERO_ADDRESS);

const nativeSymbol = params.chainMetadata.nativeCurrency.symbol;
const nativeDecimals = params.chainMetadata.nativeCurrency.decimals;

const [token0Symbol, token1Symbol, token0Decimals, token1Decimals] =
await Promise.all([
isToken0Native
? nativeSymbol
: symbol({
contract: token0Contract,
}),
isToken1Native
? nativeSymbol
: symbol({
contract: token1Contract,
}),
isToken0Native
? nativeDecimals
: decimals({
contract: token0Contract,
}),
isToken1Native
? nativeDecimals
: decimals({
contract: token1Contract,
}),
Comment on lines +74 to +101
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Native token detection still misses NATIVE_TOKEN_ADDRESS.

collect/positions will continue to throw for native payouts because thirdweb encodes the native asset as 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, not 0x000…000. When a reward uses that sentinel, we still call symbol()/decimals() on a non-existent ERC‑20 and the RPC returns empty data, so this function rejects and the page breaks again. Extend the check to treat both ZERO_ADDRESS and NATIVE_TOKEN_ADDRESS (or call the shared helper) as native before attempting any contract reads.

-import { getAddress, getContract, readContract, ZERO_ADDRESS } from "thirdweb";
+import {
+  getAddress,
+  getContract,
+  readContract,
+  ZERO_ADDRESS,
+  NATIVE_TOKEN_ADDRESS,
+} from "thirdweb";-  const isToken0Native = getAddress(token0Address) === getAddress(ZERO_ADDRESS);
-  const isToken1Native = getAddress(token1Address) === getAddress(ZERO_ADDRESS);
+  const normalizedToken0 = getAddress(token0Address);
+  const normalizedToken1 = getAddress(token1Address);
+  const zero = getAddress(ZERO_ADDRESS);
+  const native = getAddress(NATIVE_TOKEN_ADDRESS);
+
+  const isToken0Native = normalizedToken0 === zero || normalizedToken0 === native;
+  const isToken1Native = normalizedToken1 === zero || normalizedToken1 === native;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isToken0Native = getAddress(token0Address) === getAddress(ZERO_ADDRESS);
const isToken1Native = getAddress(token1Address) === getAddress(ZERO_ADDRESS);
const nativeSymbol = params.chainMetadata.nativeCurrency.symbol;
const nativeDecimals = params.chainMetadata.nativeCurrency.decimals;
const [token0Symbol, token1Symbol, token0Decimals, token1Decimals] =
await Promise.all([
isToken0Native
? nativeSymbol
: symbol({
contract: token0Contract,
}),
isToken1Native
? nativeSymbol
: symbol({
contract: token1Contract,
}),
isToken0Native
? nativeDecimals
: decimals({
contract: token0Contract,
}),
isToken1Native
? nativeDecimals
: decimals({
contract: token1Contract,
}),
// apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/rewards/utils/unclaimed-fees.ts
import {
getAddress,
getContract,
readContract,
ZERO_ADDRESS,
NATIVE_TOKEN_ADDRESS,
} from "thirdweb";
// …
// Normalize addresses once for clearer comparisons
const normalizedToken0 = getAddress(token0Address);
const normalizedToken1 = getAddress(token1Address);
const zero = getAddress(ZERO_ADDRESS);
const native = getAddress(NATIVE_TOKEN_ADDRESS);
// Treat both the zero address and the native‐token sentinel as “native”
const isToken0Native = normalizedToken0 === zero || normalizedToken0 === native;
const isToken1Native = normalizedToken1 === zero || normalizedToken1 === native;
const nativeSymbol = params.chainMetadata.nativeCurrency.symbol;
const nativeDecimals = params.chainMetadata.nativeCurrency.decimals;
const [token0Symbol, token1Symbol, token0Decimals, token1Decimals] =
await Promise.all([
isToken0Native
? nativeSymbol
: symbol({
contract: token0Contract,
}),
isToken1Native
? nativeSymbol
: symbol({
contract: token1Contract,
}),
isToken0Native
? nativeDecimals
: decimals({
contract: token0Contract,
}),
isToken1Native
? nativeDecimals
: decimals({
contract: token1Contract,
}),
// …

]);

return {
token0: {
address: token0Address,
amount: collectResult[0],
symbol: token0Symbol,
decimals: token0Decimals,
},
token1: {
address: token1Address,
amount: collectResult[1],
symbol: token1Symbol,
decimals: token1Decimals,
},
};
}
Loading