diff --git a/apps/web/src/config/abi/ido.ts b/apps/web/src/config/abi/ido.ts
new file mode 100644
index 0000000000000..3ef309652f39f
--- /dev/null
+++ b/apps/web/src/config/abi/ido.ts
@@ -0,0 +1,260 @@
+export const idoABI = [
+  { inputs: [], stateMutability: 'nonpayable', type: 'constructor' },
+  { inputs: [], name: 'AddressesLengthNotCorrect', type: 'error' },
+  { inputs: [], name: 'AlreadyHarvested', type: 'error' },
+  { inputs: [], name: 'AlreadyInitialized', type: 'error' },
+  { inputs: [], name: 'AmountMustBeZero', type: 'error' },
+  { inputs: [], name: 'AmountMustExceedZero', type: 'error' },
+  { inputs: [], name: 'CanNotBeLPToken', type: 'error' },
+  { inputs: [], name: 'CanNotBeOfferingToken', type: 'error' },
+  { inputs: [], name: 'DidNotParticipate', type: 'error' },
+  { inputs: [], name: 'EmptyUserAddress', type: 'error' },
+  { inputs: [], name: 'EndTimeTooFar', type: 'error' },
+  { inputs: [], name: 'FlatTaxRateMustBe0WhenHasTaxIsFalse', type: 'error' },
+  { inputs: [], name: 'FlatTaxRateMustBeLessThan1e12', type: 'error' },
+  { inputs: [], name: 'IDOHasEnded', type: 'error' },
+  { inputs: [], name: 'IDOHasStarted', type: 'error' },
+  { inputs: [], name: 'NewAmountAboveUserCap', type: 'error' },
+  { inputs: [], name: 'NotEnoughLPTokens', type: 'error' },
+  { inputs: [], name: 'NotEnoughOfferingTokens', type: 'error' },
+  { inputs: [], name: 'NotFactory', type: 'error' },
+  { inputs: [], name: 'NotMeetAnyoneOfRequiredConditions', type: 'error' },
+  { inputs: [], name: 'PoolNotSet', type: 'error' },
+  { inputs: [], name: 'StartAndEndTimestampsLengthNotCorrect', type: 'error' },
+  { inputs: [], name: 'StartTimeMustGreaterThanCurrentBlockTime', type: 'error' },
+  { inputs: [], name: 'StartTimeMustInferiorToEndTime', type: 'error' },
+  { inputs: [], name: 'TokensNotDepositedProperly', type: 'error' },
+  { inputs: [], name: 'TooEarly', type: 'error' },
+  { inputs: [], name: 'TooLate', type: 'error' },
+  {
+    anonymous: false,
+    inputs: [
+      { indexed: false, internalType: 'address', name: 'tokenAddress', type: 'address' },
+      { indexed: false, internalType: 'uint256', name: 'amountTokens', type: 'uint256' },
+    ],
+    name: 'AdminTokenRecovery',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      { indexed: false, internalType: 'uint256', name: 'amountLP', type: 'uint256' },
+      { indexed: false, internalType: 'uint256', name: 'amountOfferingToken', type: 'uint256' },
+    ],
+    name: 'AdminWithdraw',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      { indexed: true, internalType: 'address', name: 'user', type: 'address' },
+      { indexed: false, internalType: 'uint256', name: 'amount', type: 'uint256' },
+    ],
+    name: 'Deposit',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      { indexed: true, internalType: 'address', name: 'user', type: 'address' },
+      { indexed: false, internalType: 'uint256', name: 'offeringAmount', type: 'uint256' },
+      { indexed: false, internalType: 'uint256', name: 'excessAmount', type: 'uint256' },
+    ],
+    name: 'Harvest',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      { indexed: false, internalType: 'uint256', name: 'startTimestamp', type: 'uint256' },
+      { indexed: false, internalType: 'uint256', name: 'endTimestamp', type: 'uint256' },
+    ],
+    name: 'NewStartAndEndTimestamps',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      { indexed: true, internalType: 'address', name: 'previousOwner', type: 'address' },
+      { indexed: true, internalType: 'address', name: 'newOwner', type: 'address' },
+    ],
+    name: 'OwnershipTransferred',
+    type: 'event',
+  },
+  {
+    anonymous: false,
+    inputs: [
+      { indexed: false, internalType: 'uint256', name: 'offeringAmountPool', type: 'uint256' },
+      { indexed: false, internalType: 'uint256', name: 'raisingAmountPool', type: 'uint256' },
+    ],
+    name: 'PoolParametersSet',
+    type: 'event',
+  },
+  {
+    inputs: [],
+    name: 'MAX_BUFFER_SECONDS',
+    outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: '_poolInformation',
+    outputs: [
+      { internalType: 'uint256', name: 'raisingAmountPool', type: 'uint256' },
+      { internalType: 'uint256', name: 'offeringAmountPool', type: 'uint256' },
+      { internalType: 'uint256', name: 'capPerUserInLP', type: 'uint256' },
+      { internalType: 'bool', name: 'hasTax', type: 'bool' },
+      { internalType: 'uint256', name: 'flatTaxRate', type: 'uint256' },
+      { internalType: 'uint256', name: 'totalAmountPool', type: 'uint256' },
+      { internalType: 'uint256', name: 'sumTaxesOverflow', type: 'uint256' },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
+    name: 'addresses',
+    outputs: [{ internalType: 'address', name: '', type: 'address' }],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [{ internalType: 'uint256', name: '_amount', type: 'uint256' }],
+    name: 'depositPool',
+    outputs: [],
+    stateMutability: 'payable',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'endTimestamp',
+    outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [
+      { internalType: 'uint256', name: '_lpAmount', type: 'uint256' },
+      { internalType: 'uint256', name: '_offerAmount', type: 'uint256' },
+    ],
+    name: 'finalWithdraw',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  { inputs: [], name: 'harvestPool', outputs: [], stateMutability: 'nonpayable', type: 'function' },
+  {
+    inputs: [
+      { internalType: 'address[]', name: '_addresses', type: 'address[]' },
+      { internalType: 'uint256[]', name: '_startAndEndTimestamps', type: 'uint256[]' },
+      { internalType: 'uint256', name: '_maxBufferSeconds', type: 'uint256' },
+    ],
+    name: 'initialize',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'owner',
+    outputs: [{ internalType: 'address', name: '', type: 'address' }],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [
+      { internalType: 'address', name: '_tokenAddress', type: 'address' },
+      { internalType: 'uint256', name: '_tokenAmount', type: 'uint256' },
+    ],
+    name: 'recoverWrongTokens',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  { inputs: [], name: 'renounceOwnership', outputs: [], stateMutability: 'nonpayable', type: 'function' },
+  {
+    inputs: [
+      { internalType: 'uint256', name: '_offeringAmountPool', type: 'uint256' },
+      { internalType: 'uint256', name: '_raisingAmountPool', type: 'uint256' },
+      { internalType: 'uint256', name: '_limitPerUserInLP', type: 'uint256' },
+      { internalType: 'bool', name: '_hasTax', type: 'bool' },
+      { internalType: 'uint256', name: '_flatTaxRate', type: 'uint256' },
+    ],
+    name: 'setPool',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'startTimestamp',
+    outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [{ internalType: 'address', name: 'newOwner', type: 'address' }],
+    name: 'transferOwnership',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [{ internalType: 'uint256[]', name: '_startAndEndTimestamps', type: 'uint256[]' }],
+    name: 'updateStartAndEndTimestamps',
+    outputs: [],
+    stateMutability: 'nonpayable',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'viewPoolInformation',
+    outputs: [
+      { internalType: 'uint256', name: '', type: 'uint256' },
+      { internalType: 'uint256', name: '', type: 'uint256' },
+      { internalType: 'uint256', name: '', type: 'uint256' },
+      { internalType: 'bool', name: '', type: 'bool' },
+      { internalType: 'uint256', name: '', type: 'uint256' },
+      { internalType: 'uint256', name: '', type: 'uint256' },
+      { internalType: 'uint256', name: '', type: 'uint256' },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [],
+    name: 'viewPoolTaxRateOverflow',
+    outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [{ internalType: 'address', name: '_user', type: 'address' }],
+    name: 'viewUserAllocation',
+    outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [{ internalType: 'address', name: '_user', type: 'address' }],
+    name: 'viewUserInfo',
+    outputs: [
+      { internalType: 'uint256', name: '', type: 'uint256' },
+      { internalType: 'bool', name: '', type: 'bool' },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+  {
+    inputs: [{ internalType: 'address', name: '_user', type: 'address' }],
+    name: 'viewUserOfferingAndRefundingAmounts',
+    outputs: [
+      { internalType: 'uint256', name: '', type: 'uint256' },
+      { internalType: 'uint256', name: '', type: 'uint256' },
+      { internalType: 'uint256', name: '', type: 'uint256' },
+    ],
+    stateMutability: 'view',
+    type: 'function',
+  },
+] as const
diff --git a/apps/web/src/config/constants/contracts.ts b/apps/web/src/config/constants/contracts.ts
index e885c3cdc8576..5e8f31247c8c4 100644
--- a/apps/web/src/config/constants/contracts.ts
+++ b/apps/web/src/config/constants/contracts.ts
@@ -260,4 +260,7 @@ export default {
     [ChainId.ZKSYNC_TESTNET]: '0xbfcCF87Ee5cd03d4550Cc1526Bf152cc2EE1C7AB',
     [ChainId.ZKSYNC]: '0xB774c13bA5a665713037c42A12f0ED9De70585cB',
   },
+  ido: {
+    [ChainId.BSC_TESTNET]: '0xCd2358dd6FD92447ACAdB9f1A437A658151a2C25',
+  },
 } as const satisfies Record<string, Record<number, `0x${string}`>>
diff --git a/apps/web/src/hooks/useContract.ts b/apps/web/src/hooks/useContract.ts
index 96acc756051bd..cb7f9023dfa25 100644
--- a/apps/web/src/hooks/useContract.ts
+++ b/apps/web/src/hooks/useContract.ts
@@ -28,6 +28,7 @@ import {
   getFarmAuctionContract,
   getFixedStakingContract,
   getGaugesVotingContract,
+  getIDOContract,
   getIfoCreditAddressContract,
   getLotteryV2Contract,
   getMasterChefContract,
@@ -587,3 +588,10 @@ export const useRevenueSharingPoolGatewayContract = () => {
 
   return useMemo(() => getRevenueSharingPoolGatewayContract(signer ?? undefined, chainId), [signer, chainId])
 }
+
+export const useIDOContract = () => {
+  const { chainId } = useActiveChainId()
+  const { data: signer } = useWalletClient()
+
+  return useMemo(() => getIDOContract(signer ?? undefined, chainId), [chainId, signer])
+}
diff --git a/apps/web/src/utils/addressHelpers.ts b/apps/web/src/utils/addressHelpers.ts
index d25adeb298ea5..bfe40fcd55d39 100644
--- a/apps/web/src/utils/addressHelpers.ts
+++ b/apps/web/src/utils/addressHelpers.ts
@@ -215,3 +215,7 @@ export const getRevenueSharingVeCakeAddressNoFallback = (chainId?: number) => {
 export const getRevenueSharingPoolGatewayAddress = (chainId?: number) => {
   return getAddressFromMap(addresses.revenueSharingPoolGateway, chainId)
 }
+
+export const getIDOAddress = (chainId?: number) => {
+  return getAddressFromMap(addresses.ido, chainId)
+}
diff --git a/apps/web/src/utils/contractHelpers.ts b/apps/web/src/utils/contractHelpers.ts
index 6f786d854c97d..248a06ae57a57 100644
--- a/apps/web/src/utils/contractHelpers.ts
+++ b/apps/web/src/utils/contractHelpers.ts
@@ -16,15 +16,16 @@ import {
   getCalcGaugesVotingAddress,
   getCrossFarmingReceiverAddress,
   getCrossFarmingSenderAddress,
+  getCrossFarmingVaultAddress,
   getFarmAuctionAddress,
   getFixedStakingAddress,
   getGaugesVotingAddress,
+  getIDOAddress,
   getLotteryV2Address,
   getMasterChefV2Address,
   getMasterChefV3Address,
   getNftMarketAddress,
   getNftSaleAddress,
-  getCrossFarmingVaultAddress,
   getPancakeProfileAddress,
   getPancakeSquadAddress,
   getPancakeVeSenderV2Address,
@@ -53,8 +54,8 @@ import {
 import { predictionsV1ABI, predictionsV2ABI, predictionsV3ABI } from '@pancakeswap/prediction'
 import { crossFarmingProxyABI } from 'config/abi/crossFarmingProxy'
 import { crossFarmingSenderABI } from 'config/abi/crossFarmingSender'
-import { nftSaleABI } from 'config/abi/nftSale'
 import { crossFarmingVaultABI } from 'config/abi/crossFarmingVault'
+import { nftSaleABI } from 'config/abi/nftSale'
 import { pointCenterIfoABI } from 'config/abi/pointCenterIfo'
 import { stableSwapNativeHelperABI } from 'config/abi/stableSwapNativeHelper'
 
@@ -82,6 +83,7 @@ import { chainlinkOracleABI } from 'config/abi/chainlinkOracle'
 import { crossFarmingReceiverABI } from 'config/abi/crossFarmingReceiver'
 import { farmAuctionABI } from 'config/abi/farmAuction'
 import { fixedStakingABI } from 'config/abi/fixedStaking'
+import { idoABI } from 'config/abi/ido'
 import { lotteryV2ABI } from 'config/abi/lotteryV2'
 import { lpTokenABI } from 'config/abi/lpTokenAbi'
 import { masterChefV2ABI } from 'config/abi/masterchefV2'
@@ -592,3 +594,12 @@ export const getRevenueSharingPoolGatewayContract = (signer?: WalletClient, chai
     chainId,
   })
 }
+
+export const getIDOContract = (signer?: WalletClient, chainId?: number) => {
+  return getContract({
+    abi: idoABI,
+    address: getIDOAddress(chainId) ?? getIDOAddress(ChainId.BSC),
+    signer,
+    chainId,
+  })
+}
diff --git a/apps/web/src/views/Idos/hooks/ido/usdIDOStatus.ts b/apps/web/src/views/Idos/hooks/ido/usdIDOStatus.ts
new file mode 100644
index 0000000000000..12eb11833b83e
--- /dev/null
+++ b/apps/web/src/views/Idos/hooks/ido/usdIDOStatus.ts
@@ -0,0 +1,29 @@
+import { type Currency, CurrencyAmount, Percent } from '@pancakeswap/swap-sdk-core'
+import { useMemo } from 'react'
+import { useIDOCurrencies } from './useIDOCurrencies'
+import { useIDOPoolInfo } from './useIDOPoolInfo'
+
+export type IDOStatus = {
+  progress: Percent
+  currentStakedAmount: CurrencyAmount<Currency>
+}
+
+export const useIDOStatus = () => {
+  const { stakeCurrency } = useIDOCurrencies()
+  const { data: poolInfo } = useIDOPoolInfo()
+
+  const progress = useMemo(() => {
+    if (!poolInfo) return new Percent(0, 100)
+    return new Percent(poolInfo.totalAmountPool, poolInfo.raisingAmountPool)
+  }, [poolInfo])
+
+  const currentStakedAmount = useMemo(() => {
+    if (!stakeCurrency || !poolInfo) return undefined
+    return CurrencyAmount.fromRawAmount(stakeCurrency, poolInfo.totalAmountPool)
+  }, [poolInfo, stakeCurrency])
+
+  return {
+    progress,
+    currentStakedAmount,
+  }
+}
diff --git a/apps/web/src/views/Idos/hooks/ido/useIDOClaimCallback.tsx b/apps/web/src/views/Idos/hooks/ido/useIDOClaimCallback.tsx
new file mode 100644
index 0000000000000..4f157a147841b
--- /dev/null
+++ b/apps/web/src/views/Idos/hooks/ido/useIDOClaimCallback.tsx
@@ -0,0 +1,30 @@
+import { useTranslation } from '@pancakeswap/localization'
+import { useToast } from '@pancakeswap/uikit'
+import { ToastDescriptionWithTx } from 'components/Toast'
+import useAccountActiveChain from 'hooks/useAccountActiveChain'
+import useCatchTxError from 'hooks/useCatchTxError'
+import { useIDOContract } from 'hooks/useContract'
+import { useCallback } from 'react'
+
+export const useIDOClaimCallback = () => {
+  const idoContract = useIDOContract()
+  const { t } = useTranslation()
+  const { account } = useAccountActiveChain()
+  const { toastSuccess } = useToast()
+  const { fetchWithCatchTxError, loading: isPending } = useCatchTxError()
+
+  const claim = useCallback(async () => {
+    if (!account || !idoContract) return
+    const receipt = await fetchWithCatchTxError(() =>
+      idoContract.write.harvestPool({
+        account,
+        chain: idoContract.chain,
+      }),
+    )
+    if (receipt?.status) {
+      toastSuccess(t('Claim successful'), <ToastDescriptionWithTx txHash={receipt.transactionHash} />)
+    }
+  }, [account, idoContract, fetchWithCatchTxError, toastSuccess, t])
+
+  return { claim, isPending }
+}
diff --git a/apps/web/src/views/Idos/hooks/ido/useIDOConfig.ts b/apps/web/src/views/Idos/hooks/ido/useIDOConfig.ts
new file mode 100644
index 0000000000000..d196403cdb7e0
--- /dev/null
+++ b/apps/web/src/views/Idos/hooks/ido/useIDOConfig.ts
@@ -0,0 +1,40 @@
+import { type Currency, CurrencyAmount, Price } from '@pancakeswap/swap-sdk-core'
+import { useMemo } from 'react'
+import { useIDOCurrencies } from './useIDOCurrencies'
+import { useIDOPoolInfo } from './useIDOPoolInfo'
+
+export type IDOConfig = {
+  totalSale: bigint
+  startTimestamp: number
+  endTimestamp: number
+  duration: number
+  pricePerToken: Price<Currency, Currency> | undefined
+  maxStakePerUser: CurrencyAmount<Currency> | undefined
+}
+
+export const useIDOConfig = () => {
+  const { data: poolInfo } = useIDOPoolInfo()
+  const { stakeCurrency, offeringCurrency } = useIDOCurrencies()
+
+  return useMemo(() => {
+    return {
+      totalSale: poolInfo?.offeringAmountPool ?? 0n,
+      startTimestamp: poolInfo?.startTimestamp ?? 0,
+      endTimestamp: poolInfo?.endTimestamp ?? 0,
+      duration:
+        poolInfo?.endTimestamp && poolInfo?.startTimestamp ? poolInfo?.endTimestamp - poolInfo?.startTimestamp : 0,
+      pricePerToken:
+        stakeCurrency && offeringCurrency
+          ? new Price(
+              stakeCurrency,
+              offeringCurrency,
+              poolInfo?.raisingAmountPool ?? 0n,
+              poolInfo?.offeringAmountPool ?? 0n,
+            )
+          : undefined,
+      maxStakePerUser: stakeCurrency
+        ? CurrencyAmount.fromRawAmount(stakeCurrency, poolInfo?.capPerUserInLP ?? 0n)
+        : undefined,
+    } satisfies IDOConfig
+  }, [poolInfo, stakeCurrency, offeringCurrency])
+}
diff --git a/apps/web/src/views/Idos/hooks/ido/useIDOCurrencies.ts b/apps/web/src/views/Idos/hooks/ido/useIDOCurrencies.ts
new file mode 100644
index 0000000000000..0d1c8dad4492c
--- /dev/null
+++ b/apps/web/src/views/Idos/hooks/ido/useIDOCurrencies.ts
@@ -0,0 +1,69 @@
+import { useQuery } from '@tanstack/react-query'
+import { QUERY_SETTINGS_IMMUTABLE } from 'config/constants'
+import { useCurrency } from 'hooks/Tokens'
+import { useActiveChainId } from 'hooks/useActiveChainId'
+import { useIDOContract } from 'hooks/useContract'
+import { getViemClients } from 'utils/viem'
+import type { Address } from 'viem/accounts'
+
+type IDOAddresses = {
+  lpToken: Address
+  offeringToken: Address
+  adminAddress: Address
+}
+
+export const useIDOAddresses = () => {
+  const { chainId } = useActiveChainId()
+  const idoContract = useIDOContract()
+
+  return useQuery({
+    queryKey: ['idoAddresses', chainId],
+    queryFn: async (): Promise<IDOAddresses> => {
+      const publicClient = getViemClients({ chainId })
+      if (!idoContract || !publicClient) throw new Error('IDO contract not found')
+
+      const [lpToken, offeringToken, adminAddress] = await publicClient.multicall({
+        allowFailure: false,
+        contracts: [
+          {
+            address: idoContract.address,
+            abi: idoContract.abi,
+            functionName: 'addresses',
+            args: [0n],
+          },
+          {
+            address: idoContract.address,
+            abi: idoContract.abi,
+            functionName: 'addresses',
+            args: [1n],
+          },
+          {
+            address: idoContract.address,
+            abi: idoContract.abi,
+            functionName: 'addresses',
+            args: [2n],
+          },
+        ],
+      })
+
+      return {
+        lpToken,
+        offeringToken,
+        adminAddress,
+      }
+    },
+    enabled: !!idoContract,
+    ...QUERY_SETTINGS_IMMUTABLE,
+  })
+}
+
+export const useIDOCurrencies = () => {
+  const { data: addresses } = useIDOAddresses()
+  const stakeCurrency = useCurrency(addresses?.lpToken)
+  const offeringCurrency = useCurrency(addresses?.offeringToken)
+
+  return {
+    stakeCurrency,
+    offeringCurrency,
+  }
+}
diff --git a/apps/web/src/views/Idos/hooks/ido/useIDODepositCallback.tsx b/apps/web/src/views/Idos/hooks/ido/useIDODepositCallback.tsx
new file mode 100644
index 0000000000000..2db83723dd913
--- /dev/null
+++ b/apps/web/src/views/Idos/hooks/ido/useIDODepositCallback.tsx
@@ -0,0 +1,40 @@
+import { useTranslation } from '@pancakeswap/localization'
+import type { Currency, CurrencyAmount } from '@pancakeswap/swap-sdk-core'
+import { useToast } from '@pancakeswap/uikit'
+import { ToastDescriptionWithTx } from 'components/Toast'
+import useAccountActiveChain from 'hooks/useAccountActiveChain'
+import useCatchTxError from 'hooks/useCatchTxError'
+import { useIDOContract } from 'hooks/useContract'
+import { useCallback } from 'react'
+
+export const useIDODepositCallback = () => {
+  const idoContract = useIDOContract()
+  const { t } = useTranslation()
+  const { account } = useAccountActiveChain()
+  const { toastSuccess } = useToast()
+  const { fetchWithCatchTxError, loading: isPending } = useCatchTxError()
+
+  const deposit = useCallback(
+    async (amount: CurrencyAmount<Currency>) => {
+      if (!account || !idoContract) return
+      const value = amount.currency.isNative ? amount.quotient : 0n
+      const amountPool = amount.currency.isNative ? 0n : amount.quotient
+      const receipt = await fetchWithCatchTxError(() =>
+        idoContract.write.depositPool([amountPool], {
+          account,
+          chain: idoContract.chain,
+          value,
+        }),
+      )
+      if (receipt?.status) {
+        toastSuccess(t('Deposit successful'), <ToastDescriptionWithTx txHash={receipt.transactionHash} />)
+      }
+    },
+    [account, idoContract, fetchWithCatchTxError, toastSuccess, t],
+  )
+
+  return {
+    deposit,
+    isPending,
+  }
+}
diff --git a/apps/web/src/views/Idos/hooks/ido/useIDOPoolInfo.ts b/apps/web/src/views/Idos/hooks/ido/useIDOPoolInfo.ts
new file mode 100644
index 0000000000000..1e94fb7f87ec2
--- /dev/null
+++ b/apps/web/src/views/Idos/hooks/ido/useIDOPoolInfo.ts
@@ -0,0 +1,94 @@
+import { useQuery } from '@tanstack/react-query'
+import { useActiveChainId } from 'hooks/useActiveChainId'
+import { useIDOContract } from 'hooks/useContract'
+import { getViemClients } from 'utils/viem'
+
+export type IDOPoolInfo = {
+  /**
+   * Amount of tokens raised in the pool
+   */
+  raisingAmountPool: bigint
+  /**
+   * Amount of tokens offered in the pool
+   */
+  offeringAmountPool: bigint
+  /**
+   * Maximum amount of tokens a user can stake in the pool
+   */
+  capPerUserInLP: bigint
+  /**
+   * Whether the pool has a tax
+   */
+  hasTax: boolean
+  /**
+   * Flat tax rate
+   */
+  flatTaxRate: bigint
+  /**
+   * Total amount of tokens staked in the pool
+   */
+  totalAmountPool: bigint
+  /**
+   * Sum of taxes overflow
+   */
+  sumTaxesOverflow: bigint
+  /**
+   * Start timestamp of the pool
+   */
+  startTimestamp: number
+  /**
+   * End timestamp of the pool
+   */
+  endTimestamp: number
+}
+
+export const useIDOPoolInfo = () => {
+  const { chainId } = useActiveChainId()
+  const idoContract = useIDOContract()
+
+  return useQuery({
+    queryKey: ['idoPoolInfo', chainId],
+    queryFn: async (): Promise<IDOPoolInfo> => {
+      const publicClient = getViemClients({ chainId })
+      if (!idoContract || !publicClient) throw new Error('IDO contract not found')
+
+      const [
+        [raisingAmountPool, offeringAmountPool, capPerUserInLP, hasTax, flatTaxRate, totalAmountPool, sumTaxesOverflow],
+        startTimestamp,
+        endTimestamp,
+      ] = await publicClient.multicall({
+        contracts: [
+          {
+            address: idoContract.address,
+            abi: idoContract.abi,
+            functionName: 'viewPoolInformation',
+          },
+          {
+            address: idoContract.address,
+            abi: idoContract.abi,
+            functionName: 'startTimestamp',
+          },
+          {
+            address: idoContract.address,
+            abi: idoContract.abi,
+            functionName: 'endTimestamp',
+          },
+        ],
+        allowFailure: false,
+      })
+
+      return {
+        raisingAmountPool,
+        offeringAmountPool,
+        capPerUserInLP,
+        hasTax,
+        flatTaxRate,
+        totalAmountPool,
+        sumTaxesOverflow,
+        startTimestamp: Number(startTimestamp),
+        endTimestamp: Number(endTimestamp),
+      }
+    },
+    enabled: !!idoContract,
+  })
+}
diff --git a/apps/web/src/views/Idos/hooks/ido/useIDOUserInfo.ts b/apps/web/src/views/Idos/hooks/ido/useIDOUserInfo.ts
new file mode 100644
index 0000000000000..dae7c8f08e188
--- /dev/null
+++ b/apps/web/src/views/Idos/hooks/ido/useIDOUserInfo.ts
@@ -0,0 +1,27 @@
+import { useQuery } from '@tanstack/react-query'
+import useAccountActiveChain from 'hooks/useAccountActiveChain'
+import { useIDOContract } from 'hooks/useContract'
+
+export type IDOUserInfo = {
+  amountPool: bigint
+  claimedPool: boolean
+}
+
+export const useIDOUserInfo = () => {
+  const { chainId, account } = useAccountActiveChain()
+  const idoContract = useIDOContract()
+
+  return useQuery({
+    queryKey: ['idoUserInfo', account, chainId],
+    queryFn: async (): Promise<IDOUserInfo> => {
+      if (!account || !idoContract) throw new Error('IDO contract not found')
+
+      const [amountPool, claimedPool] = await idoContract.read.viewUserInfo([account])
+      return {
+        amountPool,
+        claimedPool,
+      }
+    },
+    enabled: !!account && !!idoContract,
+  })
+}
diff --git a/apps/web/src/views/Idos/hooks/ido/useIDOUserStatus.ts b/apps/web/src/views/Idos/hooks/ido/useIDOUserStatus.ts
new file mode 100644
index 0000000000000..39a91d4cc2d54
--- /dev/null
+++ b/apps/web/src/views/Idos/hooks/ido/useIDOUserStatus.ts
@@ -0,0 +1,57 @@
+import { type Currency, CurrencyAmount } from '@pancakeswap/swap-sdk-core'
+import { useQuery } from '@tanstack/react-query'
+import useAccountActiveChain from 'hooks/useAccountActiveChain'
+import { useIDOContract } from 'hooks/useContract'
+import { useMemo } from 'react'
+import { useIDOCurrencies } from './useIDOCurrencies'
+import { useIDOUserInfo } from './useIDOUserInfo'
+
+export type IDOUserStatus = {
+  stakedAmount: CurrencyAmount<Currency>
+  offeringCurrency: Currency | undefined
+  stakeTax: CurrencyAmount<Currency>
+  stakeRefund: CurrencyAmount<Currency>
+}
+
+export const useIDOUserStatus = () => {
+  const { data: userInfo } = useIDOUserInfo()
+  const { data: offeringAndRefundingAmounts } = useViewUserOfferingAndRefundingAmounts()
+  const { stakeCurrency } = useIDOCurrencies()
+
+  const stakedAmount = useMemo(() => {
+    if (!stakeCurrency || !userInfo) return undefined
+    return CurrencyAmount.fromRawAmount(stakeCurrency, userInfo.amountPool)
+  }, [stakeCurrency, userInfo])
+
+  const stakeTax = useMemo(() => {
+    if (!stakeCurrency) return undefined
+    return CurrencyAmount.fromRawAmount(stakeCurrency, offeringAndRefundingAmounts?.userTaxAmount ?? 0n)
+  }, [stakeCurrency, offeringAndRefundingAmounts])
+
+  const stakeRefund = useMemo(() => {
+    if (!stakeCurrency) return undefined
+    return CurrencyAmount.fromRawAmount(stakeCurrency, offeringAndRefundingAmounts?.userRefundingAmount ?? 0n)
+  }, [stakeCurrency, offeringAndRefundingAmounts])
+
+  return {
+    stakedAmount,
+    stakeTax,
+    stakeRefund,
+  }
+}
+
+const useViewUserOfferingAndRefundingAmounts = () => {
+  const idoContract = useIDOContract()
+  const { account } = useAccountActiveChain()
+
+  return useQuery({
+    queryKey: ['idoUserOfferingAndRefundingAmounts', idoContract?.address, account],
+    queryFn: async (): Promise<{ userOfferingAmount: bigint; userRefundingAmount: bigint; userTaxAmount: bigint }> => {
+      if (!idoContract) throw new Error('IDO contract not found')
+      const [userOfferingAmount, userRefundingAmount, userTaxAmount] =
+        await idoContract.read.viewUserOfferingAndRefundingAmounts([account!])
+      return { userOfferingAmount, userRefundingAmount, userTaxAmount }
+    },
+    enabled: !!account && !!idoContract,
+  })
+}